From 126424119bca114aedd2f25d4b994fe62180dc78 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 14 May 2024 18:53:14 +0300 Subject: [PATCH 1/9] highlight nodes shuffled out to auction list --- .../disabled/disabledNodesCoordinator.go | 5 + process/peer/process.go | 5 +- process/peer/process_test.go | 14 +- sharding/nodesCoordinator/dtos.go | 1 + .../nodesCoordinator/hashValidatorShuffler.go | 2 + .../indexHashedNodesCoordinator.go | 25 +++- ...shedNodesCoordinatorRegistryWithAuction.go | 9 +- sharding/nodesCoordinator/interface.go | 8 +- .../nodesCoordinatorRegistryWithAuction.pb.go | 131 ++++++++++++------ .../nodesCoordinatorRegistryWithAuction.proto | 15 +- .../shardingMocks/nodesCoordinatorMock.go | 45 +++--- .../shardingMocks/nodesCoordinatorStub.go | 6 + 12 files changed, 187 insertions(+), 79 deletions(-) diff --git a/epochStart/bootstrap/disabled/disabledNodesCoordinator.go b/epochStart/bootstrap/disabled/disabledNodesCoordinator.go index efee420feec..f7c1502d0c4 100644 --- a/epochStart/bootstrap/disabled/disabledNodesCoordinator.go +++ b/epochStart/bootstrap/disabled/disabledNodesCoordinator.go @@ -54,6 +54,11 @@ func (n *nodesCoordinator) GetAllShuffledOutValidatorsPublicKeys(_ uint32) (map[ return nil, nil } +// GetShuffledOutToAuctionValidatorsPublicKeys - +func (n *nodesCoordinator) GetShuffledOutToAuctionValidatorsPublicKeys(_ uint32) (map[uint32][][]byte, error) { + return nil, nil +} + // GetConsensusValidatorsPublicKeys - func (n *nodesCoordinator) GetConsensusValidatorsPublicKeys(_ []byte, _ uint64, _ uint32, _ uint32) ([]string, error) { return nil, nil diff --git a/process/peer/process.go b/process/peer/process.go index 4c04de6a25d..579d4a16930 100644 --- a/process/peer/process.go +++ b/process/peer/process.go @@ -13,6 +13,8 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/errChan" "github.com/multiversx/mx-chain-go/common/validatorInfo" @@ -23,7 +25,6 @@ import ( "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/accounts" "github.com/multiversx/mx-chain-go/state/parsers" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("process/peer") @@ -197,7 +198,7 @@ func (vs *validatorStatistics) saveNodesCoordinatorUpdates(epoch uint32) (bool, nodeForcedToRemain = nodeForcedToRemain || tmpNodeForcedToRemain if vs.enableEpochsHandler.IsFlagEnabled(common.StakingV4Step2Flag) { - nodesMap, err = vs.nodesCoordinator.GetAllShuffledOutValidatorsPublicKeys(epoch) + nodesMap, err = vs.nodesCoordinator.GetShuffledOutToAuctionValidatorsPublicKeys(epoch) if err != nil { return false, err } diff --git a/process/peer/process_test.go b/process/peer/process_test.go index 69adb3e936a..d4c85a5601f 100644 --- a/process/peer/process_test.go +++ b/process/peer/process_test.go @@ -14,6 +14,10 @@ import ( "github.com/multiversx/mx-chain-core-go/core/keyValStorage" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/dataRetriever" @@ -33,9 +37,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/shardingMocks" stateMock "github.com/multiversx/mx-chain-go/testscommon/state" storageStubs "github.com/multiversx/mx-chain-go/testscommon/storage" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) const ( @@ -2719,6 +2720,13 @@ func TestValidatorStatisticsProcessor_SaveNodesCoordinatorUpdatesWithStakingV4(t } return mapNodes, nil }, + GetShuffledOutToAuctionValidatorsPublicKeysCalled: func(epoch uint32) (map[uint32][][]byte, error) { + mapNodes := map[uint32][][]byte{ + 0: {pk1}, + core.MetachainShardId: {pk2}, + } + return mapNodes, nil + }, } stakingV4Step2EnableEpochCalledCt := 0 arguments.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ diff --git a/sharding/nodesCoordinator/dtos.go b/sharding/nodesCoordinator/dtos.go index ab54bdeb4fa..75c28194a6a 100644 --- a/sharding/nodesCoordinator/dtos.go +++ b/sharding/nodesCoordinator/dtos.go @@ -20,4 +20,5 @@ type ResUpdateNodes struct { ShuffledOut map[uint32][]Validator Leaving []Validator StillRemaining []Validator + LowWaitingList bool } diff --git a/sharding/nodesCoordinator/hashValidatorShuffler.go b/sharding/nodesCoordinator/hashValidatorShuffler.go index ceecc9ca352..7c54e132ffc 100644 --- a/sharding/nodesCoordinator/hashValidatorShuffler.go +++ b/sharding/nodesCoordinator/hashValidatorShuffler.go @@ -10,6 +10,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/atomic" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing/sha256" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/epochStart" @@ -350,6 +351,7 @@ func shuffleNodes(arg shuffleNodesArg) (*ResUpdateNodes, error) { ShuffledOut: shuffledOutMap, Leaving: actualLeaving, StillRemaining: stillRemainingInLeaving, + LowWaitingList: lowWaitingList, }, nil } diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinator.go b/sharding/nodesCoordinator/indexHashedNodesCoordinator.go index f70bce06b04..4deb3f01bcd 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinator.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinator.go @@ -15,11 +15,12 @@ import ( "github.com/multiversx/mx-chain-core-go/data/endProcess" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/storage" - logger "github.com/multiversx/mx-chain-logger-go" ) var _ NodesCoordinator = (*indexHashedNodesCoordinator)(nil) @@ -68,6 +69,7 @@ type epochNodesConfig struct { newList []Validator auctionList []Validator mutNodesMaps sync.RWMutex + lowWaitingList bool } type indexHashedNodesCoordinator struct { @@ -122,6 +124,7 @@ func NewIndexHashedNodesCoordinator(arguments ArgNodesCoordinator) (*indexHashed shuffledOutMap: make(map[uint32][]Validator), newList: make([]Validator, 0), auctionList: make([]Validator, 0), + lowWaitingList: false, } // todo: if not genesis, use previous randomness from start of epoch meta block @@ -546,6 +549,26 @@ func (ihnc *indexHashedNodesCoordinator) GetAllShuffledOutValidatorsPublicKeys(e return validatorsPubKeys, nil } +// GetShuffledOutToAuctionValidatorsPublicKeys will return shuffled out to auction validators public keys +func (ihnc *indexHashedNodesCoordinator) GetShuffledOutToAuctionValidatorsPublicKeys(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) + } + + if nodesConfig.lowWaitingList { + // in case of low waiting list the nodes do not go through auction but directly to waiting + return validatorsPubKeys, nil + } + + return ihnc.GetAllShuffledOutValidatorsPublicKeys(epoch) +} + // GetValidatorsIndexes will return validators indexes for a block func (ihnc *indexHashedNodesCoordinator) GetValidatorsIndexes( publicKeys []string, diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistryWithAuction.go b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistryWithAuction.go index 261aa60aefc..76deba81eaa 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistryWithAuction.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistryWithAuction.go @@ -29,10 +29,11 @@ func (ihnc *indexHashedNodesCoordinator) nodesCoordinatorToRegistryWithAuction() func epochNodesConfigToEpochValidatorsWithAuction(config *epochNodesConfig) *EpochValidatorsWithAuction { result := &EpochValidatorsWithAuction{ - Eligible: make(map[string]Validators, len(config.eligibleMap)), - Waiting: make(map[string]Validators, len(config.waitingMap)), - Leaving: make(map[string]Validators, len(config.leavingMap)), - ShuffledOut: make(map[string]Validators, len(config.shuffledOutMap)), + Eligible: make(map[string]Validators, len(config.eligibleMap)), + Waiting: make(map[string]Validators, len(config.waitingMap)), + Leaving: make(map[string]Validators, len(config.leavingMap)), + ShuffledOut: make(map[string]Validators, len(config.shuffledOutMap)), + LowWaitingList: config.lowWaitingList, } for k, v := range config.eligibleMap { diff --git a/sharding/nodesCoordinator/interface.go b/sharding/nodesCoordinator/interface.go index 68dfa9bbb15..b962c6fa50a 100644 --- a/sharding/nodesCoordinator/interface.go +++ b/sharding/nodesCoordinator/interface.go @@ -3,9 +3,10 @@ package nodesCoordinator import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/state" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) // Validator defines a node that can be allocated to a shard for participation in a consensus group as validator @@ -48,6 +49,7 @@ type PublicKeysSelector interface { GetAllWaitingValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) GetAllLeavingValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) GetAllShuffledOutValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) + GetShuffledOutToAuctionValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) GetConsensusValidatorsPublicKeys(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error) GetOwnPublicKey() []byte } @@ -68,9 +70,9 @@ type NodesCoordinatorHelper interface { // ChanceComputer provides chance computation capabilities based on a rating type ChanceComputer interface { - //GetChance returns the chances for the rating + // GetChance returns the chances for the rating GetChance(uint32) uint32 - //IsInterfaceNil verifies if the interface is nil + // IsInterfaceNil verifies if the interface is nil IsInterfaceNil() bool } diff --git a/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.pb.go b/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.pb.go index 3c69dc78080..3fa0434075a 100644 --- a/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.pb.go +++ b/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.pb.go @@ -122,10 +122,11 @@ func (m *Validators) GetData() []*SerializableValidator { } type EpochValidatorsWithAuction struct { - Eligible map[string]Validators `protobuf:"bytes,1,rep,name=Eligible,proto3" json:"Eligible" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Waiting map[string]Validators `protobuf:"bytes,2,rep,name=Waiting,proto3" json:"Waiting" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Leaving map[string]Validators `protobuf:"bytes,3,rep,name=Leaving,proto3" json:"Leaving" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - ShuffledOut map[string]Validators `protobuf:"bytes,4,rep,name=ShuffledOut,proto3" json:"ShuffledOut" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Eligible map[string]Validators `protobuf:"bytes,1,rep,name=Eligible,proto3" json:"Eligible" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Waiting map[string]Validators `protobuf:"bytes,2,rep,name=Waiting,proto3" json:"Waiting" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Leaving map[string]Validators `protobuf:"bytes,3,rep,name=Leaving,proto3" json:"Leaving" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ShuffledOut map[string]Validators `protobuf:"bytes,4,rep,name=ShuffledOut,proto3" json:"ShuffledOut" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + LowWaitingList bool `protobuf:"varint,5,opt,name=LowWaitingList,proto3" json:"LowWaitingList,omitempty"` } func (m *EpochValidatorsWithAuction) Reset() { *m = EpochValidatorsWithAuction{} } @@ -184,6 +185,13 @@ func (m *EpochValidatorsWithAuction) GetShuffledOut() map[string]Validators { return nil } +func (m *EpochValidatorsWithAuction) GetLowWaitingList() bool { + if m != nil { + return m.LowWaitingList + } + return false +} + type NodesCoordinatorRegistryWithAuction struct { CurrentEpoch uint32 `protobuf:"varint,1,opt,name=CurrentEpoch,proto3" json:"CurrentEpoch,omitempty"` EpochsConfigWithAuction map[string]*EpochValidatorsWithAuction `protobuf:"bytes,2,rep,name=EpochsConfigWithAuction,proto3" json:"EpochsConfigWithAuction,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` @@ -248,43 +256,44 @@ func init() { } var fileDescriptor_f04461c784f438d5 = []byte{ - // 561 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4f, 0x8f, 0xd2, 0x40, - 0x18, 0xc6, 0x3b, 0xb0, 0x80, 0xfb, 0x02, 0x09, 0x4e, 0x62, 0x6c, 0xc8, 0x66, 0xc0, 0x1a, 0x23, - 0x1e, 0x2c, 0x06, 0x0f, 0x1a, 0x0f, 0x26, 0x82, 0xc4, 0xf8, 0x0f, 0xdd, 0x6e, 0xe2, 0x26, 0x7b, - 0x6b, 0x61, 0x28, 0x13, 0xbb, 0x1d, 0x52, 0xa6, 0x1b, 0xf1, 0xa4, 0xf1, 0x0b, 0xf8, 0x31, 0x3c, - 0xf8, 0x11, 0xfc, 0x00, 0x7b, 0xe4, 0xc8, 0x89, 0x48, 0xb9, 0x18, 0x4e, 0xfb, 0x11, 0x0c, 0xd3, - 0xb2, 0x5b, 0x36, 0x8b, 0x6c, 0xb2, 0x9e, 0x98, 0x3e, 0x33, 0xcf, 0xef, 0x19, 0x1e, 0x5e, 0x0a, - 0xf7, 0x5c, 0xde, 0xa1, 0x83, 0x06, 0xe7, 0x5e, 0x87, 0xb9, 0xa6, 0xe0, 0x9e, 0x41, 0x6d, 0x36, - 0x10, 0xde, 0x70, 0x9f, 0x89, 0xde, 0x33, 0xbf, 0x2d, 0x18, 0x77, 0xf5, 0xbe, 0xc7, 0x05, 0xc7, - 0x29, 0xf9, 0x51, 0xbc, 0x6f, 0x33, 0xd1, 0xf3, 0x2d, 0xbd, 0xcd, 0x0f, 0xab, 0x36, 0xb7, 0x79, - 0x55, 0xca, 0x96, 0xdf, 0x95, 0x4f, 0xf2, 0x41, 0xae, 0x42, 0x97, 0xf6, 0x0d, 0xc1, 0x8d, 0x3d, - 0xea, 0x31, 0xd3, 0x61, 0x9f, 0x4d, 0xcb, 0xa1, 0x1f, 0x4c, 0x87, 0x75, 0x16, 0x41, 0x58, 0x83, - 0xf4, 0x7b, 0xdf, 0x7a, 0x4d, 0x87, 0x2a, 0x2a, 0xa3, 0x4a, 0xae, 0x0e, 0xf3, 0x49, 0x29, 0xdd, - 0x97, 0x8a, 0x11, 0xed, 0xe0, 0x3b, 0x90, 0x69, 0xf4, 0x4c, 0xb7, 0x4d, 0x07, 0x6a, 0xa2, 0x8c, - 0x2a, 0xf9, 0x7a, 0x76, 0x3e, 0x29, 0x65, 0xda, 0xa1, 0x64, 0x2c, 0xf7, 0x70, 0x09, 0x52, 0x2f, - 0xdd, 0x0e, 0xfd, 0xa4, 0x26, 0xe5, 0xa1, 0xed, 0xf9, 0xa4, 0x94, 0x62, 0x0b, 0xc1, 0x08, 0x75, - 0xed, 0x29, 0xc0, 0x69, 0xf0, 0x00, 0x3f, 0x80, 0xad, 0xe7, 0xa6, 0x30, 0x55, 0x54, 0x4e, 0x56, - 0xb2, 0xb5, 0x9d, 0xf0, 0xa6, 0xfa, 0x85, 0xb7, 0x34, 0xe4, 0x49, 0xed, 0x67, 0x0a, 0x8a, 0xcd, - 0x3e, 0x6f, 0xf7, 0xce, 0x28, 0xb1, 0x82, 0xf0, 0x2e, 0x5c, 0x6b, 0x3a, 0xcc, 0x66, 0x96, 0x43, - 0x23, 0x68, 0x35, 0x82, 0xae, 0x37, 0xe9, 0x4b, 0x47, 0xd3, 0x15, 0xde, 0xb0, 0xbe, 0x75, 0x3c, - 0x29, 0x29, 0xc6, 0x29, 0x06, 0xb7, 0x20, 0xb3, 0x6f, 0x32, 0xc1, 0x5c, 0x5b, 0x4d, 0x48, 0xa2, - 0xbe, 0x99, 0x18, 0x19, 0xe2, 0xc0, 0x25, 0x64, 0xc1, 0x7b, 0x43, 0xcd, 0xa3, 0x05, 0x2f, 0x79, - 0x59, 0x5e, 0x64, 0x58, 0xe1, 0x45, 0x1a, 0x3e, 0x80, 0xec, 0x5e, 0xcf, 0xef, 0x76, 0x1d, 0xda, - 0x79, 0xe7, 0x0b, 0x75, 0x4b, 0x32, 0x6b, 0x9b, 0x99, 0x31, 0x53, 0x9c, 0x1b, 0x87, 0x15, 0x5b, - 0x90, 0x5f, 0x29, 0x07, 0x17, 0x20, 0xf9, 0x31, 0x9a, 0x93, 0x6d, 0x63, 0xb1, 0xc4, 0x77, 0x21, - 0x75, 0x64, 0x3a, 0x3e, 0x95, 0x63, 0x91, 0xad, 0x5d, 0x8f, 0x82, 0xcf, 0x32, 0x8d, 0x70, 0xff, - 0x49, 0xe2, 0x31, 0x2a, 0xbe, 0x85, 0x5c, 0xbc, 0x9a, 0xff, 0x80, 0x8b, 0x37, 0x73, 0x55, 0xdc, - 0x2e, 0x14, 0xce, 0x97, 0x72, 0x45, 0xa4, 0xf6, 0x2b, 0x01, 0xb7, 0x5b, 0x9b, 0xff, 0xd8, 0x58, - 0x83, 0x5c, 0xc3, 0xf7, 0x3c, 0xea, 0x0a, 0xf9, 0x8b, 0xc9, 0xbc, 0xbc, 0xb1, 0xa2, 0xe1, 0xaf, - 0x08, 0x6e, 0xca, 0xd5, 0xa0, 0xc1, 0xdd, 0x2e, 0xb3, 0x63, 0xfe, 0x68, 0x32, 0x5f, 0x44, 0x77, - 0xb9, 0x44, 0xa2, 0xbe, 0x86, 0x24, 0xbf, 0xb5, 0xb1, 0x2e, 0xa7, 0x78, 0x08, 0x3b, 0xff, 0x32, - 0x5e, 0x50, 0xd7, 0xa3, 0xd5, 0xba, 0x6e, 0x6d, 0x1c, 0xcc, 0x58, 0x7d, 0xf5, 0x57, 0xa3, 0x29, - 0x51, 0xc6, 0x53, 0xa2, 0x9c, 0x4c, 0x09, 0xfa, 0x12, 0x10, 0xf4, 0x23, 0x20, 0xe8, 0x38, 0x20, - 0x68, 0x14, 0x10, 0x34, 0x0e, 0x08, 0xfa, 0x1d, 0x10, 0xf4, 0x27, 0x20, 0xca, 0x49, 0x40, 0xd0, - 0xf7, 0x19, 0x51, 0x46, 0x33, 0xa2, 0x8c, 0x67, 0x44, 0x39, 0x28, 0x9c, 0x7f, 0x9d, 0x5a, 0x69, - 0x19, 0xfc, 0xf0, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x45, 0x19, 0xc5, 0xc4, 0x69, 0x05, 0x00, - 0x00, + // 580 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xc1, 0x8e, 0xd2, 0x40, + 0x18, 0xc7, 0x3b, 0x40, 0x61, 0x77, 0x00, 0x83, 0x93, 0x18, 0x1b, 0xb2, 0x19, 0xb0, 0x46, 0xc5, + 0x83, 0xc5, 0xe0, 0x41, 0xe3, 0xc1, 0x44, 0x90, 0x18, 0x15, 0xd1, 0xed, 0x26, 0x6e, 0xb2, 0xb7, + 0x16, 0x86, 0x32, 0xb1, 0xdb, 0x21, 0xed, 0x74, 0x15, 0x4f, 0x1a, 0x5f, 0xc0, 0xc7, 0xf0, 0x21, + 0x7c, 0x80, 0x3d, 0x72, 0xf0, 0xc0, 0x89, 0x48, 0xb9, 0x18, 0x4e, 0xfb, 0x08, 0x86, 0xa1, 0xec, + 0x16, 0xb2, 0xc8, 0x26, 0xbb, 0x27, 0x66, 0xfe, 0x33, 0xff, 0xdf, 0xf7, 0xf1, 0xef, 0x97, 0x81, + 0xf7, 0x1d, 0xd6, 0x26, 0x5e, 0x8d, 0x31, 0xb7, 0x4d, 0x1d, 0x83, 0x33, 0x57, 0x27, 0x16, 0xf5, + 0xb8, 0xdb, 0xdf, 0xa7, 0xbc, 0xfb, 0xdc, 0x6f, 0x71, 0xca, 0x1c, 0xad, 0xe7, 0x32, 0xce, 0x90, + 0x2c, 0x7e, 0xf2, 0x0f, 0x2c, 0xca, 0xbb, 0xbe, 0xa9, 0xb5, 0xd8, 0x61, 0xd9, 0x62, 0x16, 0x2b, + 0x0b, 0xd9, 0xf4, 0x3b, 0x62, 0x27, 0x36, 0x62, 0x35, 0x77, 0xa9, 0xdf, 0x01, 0xbc, 0xb1, 0x47, + 0x5c, 0x6a, 0xd8, 0xf4, 0x8b, 0x61, 0xda, 0xe4, 0x83, 0x61, 0xd3, 0xf6, 0xac, 0x10, 0x52, 0x61, + 0xf2, 0xbd, 0x6f, 0xbe, 0x21, 0x7d, 0x05, 0x14, 0x41, 0x29, 0x53, 0x85, 0xd3, 0x51, 0x21, 0xd9, + 0x13, 0x8a, 0x1e, 0x9e, 0xa0, 0x3b, 0x30, 0x55, 0xeb, 0x1a, 0x4e, 0x8b, 0x78, 0x4a, 0xac, 0x08, + 0x4a, 0xd9, 0x6a, 0x7a, 0x3a, 0x2a, 0xa4, 0x5a, 0x73, 0x49, 0x5f, 0x9c, 0xa1, 0x02, 0x94, 0x5f, + 0x39, 0x6d, 0xf2, 0x59, 0x89, 0x8b, 0x4b, 0xdb, 0xd3, 0x51, 0x41, 0xa6, 0x33, 0x41, 0x9f, 0xeb, + 0xea, 0x33, 0x08, 0x4f, 0x0b, 0x7b, 0xe8, 0x21, 0x4c, 0xbc, 0x30, 0xb8, 0xa1, 0x80, 0x62, 0xbc, + 0x94, 0xae, 0xec, 0xcc, 0x3b, 0xd5, 0xce, 0xed, 0x52, 0x17, 0x37, 0xd5, 0xdf, 0x32, 0xcc, 0xd7, + 0x7b, 0xac, 0xd5, 0x3d, 0xa3, 0x44, 0x02, 0x42, 0xbb, 0x70, 0xab, 0x6e, 0x53, 0x8b, 0x9a, 0x36, + 0x09, 0xa1, 0xe5, 0x10, 0xba, 0xde, 0xa4, 0x2d, 0x1c, 0x75, 0x87, 0xbb, 0xfd, 0x6a, 0xe2, 0x78, + 0x54, 0x90, 0xf4, 0x53, 0x0c, 0x6a, 0xc2, 0xd4, 0xbe, 0x41, 0x39, 0x75, 0x2c, 0x25, 0x26, 0x88, + 0xda, 0x66, 0x62, 0x68, 0x88, 0x02, 0x17, 0x90, 0x19, 0xaf, 0x41, 0x8c, 0xa3, 0x19, 0x2f, 0x7e, + 0x51, 0x5e, 0x68, 0x58, 0xe2, 0x85, 0x1a, 0x3a, 0x80, 0xe9, 0xbd, 0xae, 0xdf, 0xe9, 0xd8, 0xa4, + 0xfd, 0xce, 0xe7, 0x4a, 0x42, 0x30, 0x2b, 0x9b, 0x99, 0x11, 0x53, 0x94, 0x1b, 0x85, 0xa1, 0xbb, + 0xf0, 0x5a, 0x83, 0x7d, 0x0a, 0x3b, 0x6f, 0x50, 0x8f, 0x2b, 0x72, 0x11, 0x94, 0xb6, 0xf4, 0x15, + 0x35, 0xdf, 0x84, 0xd9, 0xa5, 0x10, 0x51, 0x0e, 0xc6, 0x3f, 0x86, 0xf3, 0xb4, 0xad, 0xcf, 0x96, + 0xe8, 0x1e, 0x94, 0x8f, 0x0c, 0xdb, 0x27, 0x62, 0x7c, 0xd2, 0x95, 0xeb, 0x61, 0x83, 0x67, 0xbd, + 0xe9, 0xf3, 0xf3, 0xa7, 0xb1, 0x27, 0x20, 0xff, 0x16, 0x66, 0xa2, 0x11, 0x5e, 0x01, 0x2e, 0x9a, + 0xe0, 0x65, 0x71, 0xbb, 0x30, 0xb7, 0x1a, 0xde, 0x25, 0x91, 0xea, 0xaf, 0x18, 0xbc, 0xdd, 0xdc, + 0xfc, 0x00, 0x20, 0x15, 0x66, 0x6a, 0xbe, 0xeb, 0x12, 0x87, 0x8b, 0x2f, 0x2b, 0xea, 0x65, 0xf5, + 0x25, 0x0d, 0x7d, 0x03, 0xf0, 0xa6, 0x58, 0x79, 0x35, 0xe6, 0x74, 0xa8, 0x15, 0xf1, 0x87, 0x13, + 0xfc, 0x32, 0xec, 0xe5, 0x02, 0x15, 0xb5, 0x35, 0x24, 0xf1, 0xaf, 0xf5, 0x75, 0x75, 0xf2, 0x87, + 0x70, 0xe7, 0x7f, 0xc6, 0x73, 0xe2, 0x7a, 0xbc, 0x1c, 0xd7, 0xad, 0x8d, 0x03, 0x1c, 0x89, 0xaf, + 0xfa, 0x7a, 0x30, 0xc6, 0xd2, 0x70, 0x8c, 0xa5, 0x93, 0x31, 0x06, 0x5f, 0x03, 0x0c, 0x7e, 0x06, + 0x18, 0x1c, 0x07, 0x18, 0x0c, 0x02, 0x0c, 0x86, 0x01, 0x06, 0x7f, 0x02, 0x0c, 0xfe, 0x06, 0x58, + 0x3a, 0x09, 0x30, 0xf8, 0x31, 0xc1, 0xd2, 0x60, 0x82, 0xa5, 0xe1, 0x04, 0x4b, 0x07, 0xb9, 0xd5, + 0x67, 0xd7, 0x4c, 0x8a, 0xc2, 0x8f, 0xfe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x65, 0xa3, 0xf9, 0xfb, + 0x91, 0x05, 0x00, 0x00, } func (this *SerializableValidator) Equal(that interface{}) bool { @@ -405,6 +414,9 @@ func (this *EpochValidatorsWithAuction) Equal(that interface{}) bool { return false } } + if this.LowWaitingList != that1.LowWaitingList { + return false + } return true } func (this *NodesCoordinatorRegistryWithAuction) Equal(that interface{}) bool { @@ -467,7 +479,7 @@ func (this *EpochValidatorsWithAuction) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 8) + s := make([]string, 0, 9) s = append(s, "&nodesCoordinator.EpochValidatorsWithAuction{") keysForEligible := make([]string, 0, len(this.Eligible)) for k, _ := range this.Eligible { @@ -521,6 +533,7 @@ func (this *EpochValidatorsWithAuction) GoString() string { if this.ShuffledOut != nil { s = append(s, "ShuffledOut: "+mapStringForShuffledOut+",\n") } + s = append(s, "LowWaitingList: "+fmt.Sprintf("%#v", this.LowWaitingList)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -652,6 +665,16 @@ func (m *EpochValidatorsWithAuction) MarshalToSizedBuffer(dAtA []byte) (int, err _ = i var l int _ = l + if m.LowWaitingList { + i-- + if m.LowWaitingList { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } if len(m.ShuffledOut) > 0 { keysForShuffledOut := make([]string, 0, len(m.ShuffledOut)) for k := range m.ShuffledOut { @@ -917,6 +940,9 @@ func (m *EpochValidatorsWithAuction) Size() (n int) { n += mapEntrySize + 1 + sovNodesCoordinatorRegistryWithAuction(uint64(mapEntrySize)) } } + if m.LowWaitingList { + n += 2 + } return n } @@ -1027,6 +1053,7 @@ func (this *EpochValidatorsWithAuction) String() string { `Waiting:` + mapStringForWaiting + `,`, `Leaving:` + mapStringForLeaving + `,`, `ShuffledOut:` + mapStringForShuffledOut + `,`, + `LowWaitingList:` + fmt.Sprintf("%v", this.LowWaitingList) + `,`, `}`, }, "") return s @@ -1817,6 +1844,26 @@ func (m *EpochValidatorsWithAuction) Unmarshal(dAtA []byte) error { } m.ShuffledOut[mapkey] = *mapvalue iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LowWaitingList", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowNodesCoordinatorRegistryWithAuction + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.LowWaitingList = bool(v != 0) default: iNdEx = preIndex skippy, err := skipNodesCoordinatorRegistryWithAuction(dAtA[iNdEx:]) diff --git a/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.proto b/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.proto index 3ff1c90acb1..d4b3ef455bd 100644 --- a/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.proto +++ b/sharding/nodesCoordinator/nodesCoordinatorRegistryWithAuction.proto @@ -8,9 +8,9 @@ option (gogoproto.stable_marshaler_all) = true; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; message SerializableValidator { - bytes PubKey = 1 [(gogoproto.jsontag) = "pubKey"]; + bytes PubKey = 1 [(gogoproto.jsontag) = "pubKey"]; uint32 Chances = 2 [(gogoproto.jsontag) = "chances"]; - uint32 Index = 3 [(gogoproto.jsontag) = "index"]; + uint32 Index = 3 [(gogoproto.jsontag) = "index"]; } message Validators { @@ -18,13 +18,14 @@ message Validators { } message EpochValidatorsWithAuction { - map Eligible = 1 [(gogoproto.nullable) = false]; - map Waiting = 2 [(gogoproto.nullable) = false]; - map Leaving = 3 [(gogoproto.nullable) = false]; - map ShuffledOut = 4 [(gogoproto.nullable) = false]; + map Eligible = 1 [(gogoproto.nullable) = false]; + map Waiting = 2 [(gogoproto.nullable) = false]; + map Leaving = 3 [(gogoproto.nullable) = false]; + map ShuffledOut = 4 [(gogoproto.nullable) = false]; + bool LowWaitingList = 5; } message NodesCoordinatorRegistryWithAuction { - uint32 CurrentEpoch = 1; + uint32 CurrentEpoch = 1; map EpochsConfigWithAuction = 2; } diff --git a/testscommon/shardingMocks/nodesCoordinatorMock.go b/testscommon/shardingMocks/nodesCoordinatorMock.go index 3ee80f88d3d..9f1b872e2ab 100644 --- a/testscommon/shardingMocks/nodesCoordinatorMock.go +++ b/testscommon/shardingMocks/nodesCoordinatorMock.go @@ -5,29 +5,31 @@ import ( "fmt" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" ) // 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 - GetValidatorsIndexesCalled func(publicKeys []string, epoch uint32) ([]uint64, error) - GetAllShuffledOutValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error) - 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) + GetAllWaitingValidatorsPublicKeysCalled func() (map[uint32][][]byte, error) + ConsensusGroupSizeCalled func(uint32) int + GetValidatorsIndexesCalled func(publicKeys []string, epoch uint32) ([]uint64, error) + GetAllShuffledOutValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error) + GetShuffledOutToAuctionValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error) + GetNumTotalEligibleCalled func() uint64 } // NewNodesCoordinatorMock - @@ -110,6 +112,15 @@ func (ncm *NodesCoordinatorMock) GetAllShuffledOutValidatorsPublicKeys(epoch uin return nil, nil } +// GetShuffledOutToAuctionValidatorsPublicKeys - +func (ncm *NodesCoordinatorMock) GetShuffledOutToAuctionValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) { + if ncm.GetShuffledOutToAuctionValidatorsPublicKeysCalled != nil { + return ncm.GetShuffledOutToAuctionValidatorsPublicKeysCalled(epoch) + } + + return nil, nil +} + // GetValidatorsIndexes - func (ncm *NodesCoordinatorMock) GetValidatorsIndexes(publicKeys []string, epoch uint32) ([]uint64, error) { if ncm.GetValidatorsIndexesCalled != nil { diff --git a/testscommon/shardingMocks/nodesCoordinatorStub.go b/testscommon/shardingMocks/nodesCoordinatorStub.go index 9f82a5256e5..a142f0509ed 100644 --- a/testscommon/shardingMocks/nodesCoordinatorStub.go +++ b/testscommon/shardingMocks/nodesCoordinatorStub.go @@ -2,6 +2,7 @@ package shardingMocks import ( "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" ) @@ -82,6 +83,11 @@ func (ncm *NodesCoordinatorStub) GetAllShuffledOutValidatorsPublicKeys(_ uint32) return nil, nil } +// GetShuffledOutToAuctionValidatorsPublicKeys - +func (ncm *NodesCoordinatorStub) GetShuffledOutToAuctionValidatorsPublicKeys(_ uint32) (map[uint32][][]byte, error) { + return nil, nil +} + // GetNumTotalEligible - func (ncm *NodesCoordinatorStub) GetNumTotalEligible() uint64 { if ncm.GetNumTotalEligibleCalled != nil { From f79acdf7b24fdd18498772b39bc8ae360a3d64ff Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 15 May 2024 13:11:01 +0300 Subject: [PATCH 2/9] fix nodes config update after shuffling and add chain simulator scenario --- .../staking/stake/stakeAndUnStake_test.go | 113 +++++++++++++++++- .../indexHashedNodesCoordinator.go | 6 +- .../indexHashedNodesCoordinatorLite.go | 2 +- ...dexHashedNodesCoordinatorWithRater_test.go | 19 +-- .../indexHashedNodesCoordinator_test.go | 27 +++-- 5 files changed, 140 insertions(+), 27 deletions(-) diff --git a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go index 57a8df77cec..c29f5cab9b0 100644 --- a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go +++ b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go @@ -12,6 +12,9 @@ import ( coreAPI "github.com/multiversx/mx-chain-core-go/data/api" "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/data/validator" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" chainSimulatorIntegrationTests "github.com/multiversx/mx-chain-go/integrationTests/chainSimulator" @@ -23,8 +26,6 @@ import ( chainSimulatorProcess "github.com/multiversx/mx-chain-go/node/chainSimulator/process" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/vm" - logger "github.com/multiversx/mx-chain-logger-go" - "github.com/stretchr/testify/require" ) const ( @@ -2383,6 +2384,114 @@ func TestChainSimulator_UnStakeOneActiveNodeAndCheckAPIAuctionList(t *testing.T) require.Equal(t, 1, numUnQualified) } +// Nodes configuration at genesis consisting of a total of 40 nodes, distributed on 3 shards + meta: +// - 4 eligible nodes/shard +// - 4 waiting nodes/shard +// - 2 nodes to shuffle per shard +// - max num nodes config for stakingV4 step3 = 32 (being downsized from previously 40 nodes) +// - with this config, we should always select max 8 nodes from auction list if there are > 40 nodes in the network +// This test will run with only 32 nodes and check that there are no nodes in the auction list, +// because of the lowWaitingList condition being triggered when in staking v4 +func TestChainSimulator_EdgeCaseLowWaitingList(t *testing.T) { + if testing.Short() { + t.Skip("this is not a short test") + } + + startTime := time.Now().Unix() + roundDurationInMillis := uint64(6000) + roundsPerEpoch := core.OptionalUint64{ + HasValue: true, + Value: 20, + } + + stakingV4Step1Epoch := uint32(2) + stakingV4Step2Epoch := uint32(3) + stakingV4Step3Epoch := uint32(4) + + numOfShards := uint32(3) + cs, err := chainSimulator.NewChainSimulator(chainSimulator.ArgsChainSimulator{ + BypassTxSignatureCheck: false, + TempDir: t.TempDir(), + PathToInitialConfig: defaultPathToInitialConfig, + NumOfShards: numOfShards, + GenesisTimestamp: startTime, + RoundDurationInMillis: roundDurationInMillis, + RoundsPerEpoch: roundsPerEpoch, + ApiInterface: api.NewNoApiInterface(), + MinNodesPerShard: 4, + MetaChainMinNodes: 4, + NumNodesWaitingListMeta: 2, + NumNodesWaitingListShard: 2, + AlterConfigsFunction: func(cfg *config.Configs) { + cfg.EpochConfig.EnableEpochs.StakingV4Step1EnableEpoch = stakingV4Step1Epoch + cfg.EpochConfig.EnableEpochs.StakingV4Step2EnableEpoch = stakingV4Step2Epoch + cfg.EpochConfig.EnableEpochs.StakingV4Step3EnableEpoch = stakingV4Step3Epoch + + cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[1].MaxNumNodes = 40 + cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[1].NodesToShufflePerShard = 2 + + cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[2].EpochEnable = stakingV4Step3Epoch + cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[2].MaxNumNodes = 32 + cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[2].NodesToShufflePerShard = 2 + }, + }) + require.Nil(t, err) + require.NotNil(t, cs) + + defer cs.Close() + + epochToCheck := int32(stakingV4Step3Epoch + 1) + err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) + require.Nil(t, err) + + metachainNode := cs.GetNodeHandler(core.MetachainShardId) + numQualified, numUnQualified := getNumQualifiedAndUnqualified(t, metachainNode) + require.Equal(t, 0, numQualified) + require.Equal(t, 0, numUnQualified) + + // we always have 0 in auction list because of the lowWaitingList condition + epochToCheck += 1 + err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) + numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) + require.Equal(t, 0, numQualified) + require.Equal(t, 0, numUnQualified) + + // stake 16 mode nodes, these will go to auction list + stakeNodes(t, cs, 16) + + epochToCheck += 1 + err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) + numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) + // all the previously registered will be selected, as we have 24 nodes in eligible+waiting, 8 will shuffle out, + // but this time there will be not be lowWaitingList, as there are enough in auction, so we will end up with + // 24-8 = 16 nodes remaining + 16 from auction, to fill up all 32 positions + require.Equal(t, 16, numQualified) + require.Equal(t, 0, numUnQualified) +} + +func stakeNodes(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator, numTxs int) { + txs := make([]*transaction.Transaction, numTxs) + for i := 0; i < numTxs; i++ { + privateKey, blsKeys, err := chainSimulator.GenerateBlsPrivateKeys(1) + require.Nil(t, err) + err = cs.AddValidatorKeys(privateKey) + require.Nil(t, err) + + mintValue := big.NewInt(0).Add(staking.MinimumStakeValue, staking.OneEGLD) + validatorOwner, err := cs.GenerateAndMintWalletAddress(core.AllShardId, mintValue) + require.Nil(t, err) + + txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature) + txs[i] = staking.GenerateTransaction(validatorOwner.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation) + } + stakeTxs, err := cs.SendTxsAndGenerateBlocksTilAreExecuted(txs, staking.MaxNumOfBlockToGenerateWhenExecutingTx) + require.Nil(t, err) + require.NotNil(t, stakeTxs) + require.Len(t, stakeTxs, numTxs) + + require.Nil(t, cs.GenerateBlocks(1)) +} + func stakeOneNode(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator) { privateKey, blsKeys, err := chainSimulator.GenerateBlsPrivateKeys(1) require.Nil(t, err) diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinator.go b/sharding/nodesCoordinator/indexHashedNodesCoordinator.go index 4deb3f01bcd..4898f018010 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinator.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinator.go @@ -159,7 +159,7 @@ func NewIndexHashedNodesCoordinator(arguments ArgNodesCoordinator) (*indexHashed ihnc.loadingFromDisk.Store(false) ihnc.nodesCoordinatorHelper = ihnc - err = ihnc.setNodesPerShards(arguments.EligibleNodes, arguments.WaitingNodes, nil, nil, arguments.Epoch) + err = ihnc.setNodesPerShards(arguments.EligibleNodes, arguments.WaitingNodes, nil, nil, arguments.Epoch, false) if err != nil { return nil, err } @@ -260,6 +260,7 @@ func (ihnc *indexHashedNodesCoordinator) setNodesPerShards( leaving map[uint32][]Validator, shuffledOut map[uint32][]Validator, epoch uint32, + lowWaitingList bool, ) error { ihnc.mutNodesConfig.Lock() defer ihnc.mutNodesConfig.Unlock() @@ -299,6 +300,7 @@ func (ihnc *indexHashedNodesCoordinator) setNodesPerShards( nodesConfig.waitingMap = waiting nodesConfig.leavingMap = leaving nodesConfig.shuffledOutMap = shuffledOut + nodesConfig.lowWaitingList = lowWaitingList nodesConfig.shardID, isCurrentNodeValidator = ihnc.computeShardForSelfPublicKey(nodesConfig) nodesConfig.selectors, err = ihnc.createSelectors(nodesConfig) if err != nil { @@ -685,7 +687,7 @@ func (ihnc *indexHashedNodesCoordinator) EpochStartPrepare(metaHdr data.HeaderHa resUpdateNodes.Leaving, ) - err = ihnc.setNodesPerShards(resUpdateNodes.Eligible, resUpdateNodes.Waiting, leavingNodesMap, resUpdateNodes.ShuffledOut, newEpoch) + err = ihnc.setNodesPerShards(resUpdateNodes.Eligible, resUpdateNodes.Waiting, leavingNodesMap, resUpdateNodes.ShuffledOut, newEpoch, resUpdateNodes.LowWaitingList) if err != nil { log.Error("set nodes per shard failed", "error", err.Error()) } diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinatorLite.go b/sharding/nodesCoordinator/indexHashedNodesCoordinatorLite.go index 3b80e8bdd23..b5b87781a73 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinatorLite.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinatorLite.go @@ -41,7 +41,7 @@ func (ihnc *indexHashedNodesCoordinator) SetNodesConfigFromValidatorsInfo(epoch resUpdateNodes.Leaving, ) - err = ihnc.setNodesPerShards(resUpdateNodes.Eligible, resUpdateNodes.Waiting, leavingNodesMap, resUpdateNodes.ShuffledOut, epoch) + err = ihnc.setNodesPerShards(resUpdateNodes.Eligible, resUpdateNodes.Waiting, leavingNodesMap, resUpdateNodes.ShuffledOut, epoch, resUpdateNodes.LowWaitingList) if err != nil { return err } diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinatorWithRater_test.go b/sharding/nodesCoordinator/indexHashedNodesCoordinatorWithRater_test.go index 40286a0c135..a80006cceae 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinatorWithRater_test.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinatorWithRater_test.go @@ -13,6 +13,9 @@ import ( "github.com/multiversx/mx-chain-core-go/data/endProcess" "github.com/multiversx/mx-chain-core-go/hashing/blake2b" "github.com/multiversx/mx-chain-core-go/hashing/sha256" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/sharding/mock" "github.com/multiversx/mx-chain-go/state" @@ -20,8 +23,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/nodeTypeProviderMock" vic "github.com/multiversx/mx-chain-go/testscommon/validatorInfoCacher" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestNewIndexHashedNodesCoordinatorWithRater_NilRaterShouldErr(t *testing.T) { @@ -48,14 +49,14 @@ func TestNewIndexHashedGroupSelectorWithRater_OkValsShouldWork(t *testing.T) { assert.Nil(t, err) } -//------- LoadEligibleList +// ------- LoadEligibleList func TestIndexHashedGroupSelectorWithRater_SetNilEligibleMapShouldErr(t *testing.T) { t.Parallel() waiting := createDummyNodesMap(2, 1, "waiting") nc, _ := NewIndexHashedNodesCoordinator(createArguments()) ihnc, _ := NewIndexHashedNodesCoordinatorWithRater(nc, &mock.RaterMock{}) - assert.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(nil, waiting, nil, nil, 0)) + assert.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(nil, waiting, nil, nil, 0, false)) } func TestIndexHashedGroupSelectorWithRater_OkValShouldWork(t *testing.T) { @@ -113,7 +114,7 @@ func TestIndexHashedGroupSelectorWithRater_OkValShouldWork(t *testing.T) { assert.Equal(t, eligibleMap[0], readEligible) } -//------- functionality tests +// ------- functionality tests func TestIndexHashedGroupSelectorWithRater_ComputeValidatorsGroup1ValidatorShouldNotCallGetRating(t *testing.T) { t.Parallel() @@ -149,7 +150,7 @@ func BenchmarkIndexHashedGroupSelectorWithRater_ComputeValidatorsGroup63of400(b consensusGroupSize := 63 list := make([]Validator, 0) - //generate 400 validators + // generate 400 validators for i := 0; i < 400; i++ { list = append(list, newValidatorMock([]byte("pk"+strconv.Itoa(i)), 1, defaultSelectionChances)) } @@ -219,7 +220,7 @@ func Test_ComputeValidatorsGroup63of400(t *testing.T) { shardSize := uint32(400) list := make([]Validator, 0) - //generate 400 validators + // generate 400 validators for i := uint32(0); i < shardSize; i++ { list = append(list, newValidatorMock([]byte(fmt.Sprintf("pk%v", i)), 1, defaultSelectionChances)) } @@ -785,7 +786,7 @@ func BenchmarkIndexHashedGroupSelectorWithRater_TestExpandList(b *testing.B) { } } - //a := []int{1, 2, 3, 4, 5, 6, 7, 8} + // a := []int{1, 2, 3, 4, 5, 6, 7, 8} rnd := rand.New(rand.NewSource(time.Now().UnixNano())) rnd.Shuffle(len(array), func(i, j int) { array[i], array[j] = array[j], array[i] }) m2 := runtime.MemStats{} @@ -820,7 +821,7 @@ func BenchmarkIndexHashedWithRaterGroupSelector_ComputeValidatorsGroup21of400(b consensusGroupSize := 21 list := make([]Validator, 0) - //generate 400 validators + // generate 400 validators for i := 0; i < 400; i++ { list = append(list, newValidatorMock([]byte("pk"+strconv.Itoa(i)), 1, defaultSelectionChances)) } diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinator_test.go b/sharding/nodesCoordinator/indexHashedNodesCoordinator_test.go index 5db65609f59..32cc2ca8326 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinator_test.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinator_test.go @@ -20,6 +20,9 @@ import ( "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/hashing/sha256" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever/dataPool" "github.com/multiversx/mx-chain-go/epochStart" @@ -31,8 +34,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/nodeTypeProviderMock" vic "github.com/multiversx/mx-chain-go/testscommon/validatorInfoCacher" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) const stakingV4Epoch = 444 @@ -145,7 +146,7 @@ func validatorsPubKeys(validators []Validator) []string { return pKeys } -//------- NewIndexHashedNodesCoordinator +// ------- NewIndexHashedNodesCoordinator func TestNewIndexHashedNodesCoordinator_NilHasherShouldErr(t *testing.T) { t.Parallel() @@ -247,7 +248,7 @@ func TestNewIndexHashedGroupSelector_OkValsShouldWork(t *testing.T) { require.Nil(t, err) } -//------- LoadEligibleList +// ------- LoadEligibleList func TestIndexHashedNodesCoordinator_SetNilEligibleMapShouldErr(t *testing.T) { t.Parallel() @@ -256,7 +257,7 @@ func TestIndexHashedNodesCoordinator_SetNilEligibleMapShouldErr(t *testing.T) { arguments := createArguments() ihnc, _ := NewIndexHashedNodesCoordinator(arguments) - require.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(nil, waitingMap, nil, nil, 0)) + require.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(nil, waitingMap, nil, nil, 0, false)) } func TestIndexHashedNodesCoordinator_SetNilWaitingMapShouldErr(t *testing.T) { @@ -266,7 +267,7 @@ func TestIndexHashedNodesCoordinator_SetNilWaitingMapShouldErr(t *testing.T) { arguments := createArguments() ihnc, _ := NewIndexHashedNodesCoordinator(arguments) - require.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(eligibleMap, nil, nil, nil, 0)) + require.Equal(t, ErrNilInputNodesMap, ihnc.setNodesPerShards(eligibleMap, nil, nil, nil, 0, false)) } func TestIndexHashedNodesCoordinator_OkValShouldWork(t *testing.T) { @@ -319,7 +320,7 @@ func TestIndexHashedNodesCoordinator_OkValShouldWork(t *testing.T) { require.Equal(t, eligibleMap[0], readEligible) } -//------- ComputeValidatorsGroup +// ------- ComputeValidatorsGroup func TestIndexHashedNodesCoordinator_NewCoordinatorGroup0SizeShouldErr(t *testing.T) { t.Parallel() @@ -401,7 +402,7 @@ func TestIndexHashedNodesCoordinator_ComputeValidatorsGroupInvalidShardIdShouldE require.Nil(t, list2) } -//------- functionality tests +// ------- functionality tests func TestIndexHashedNodesCoordinator_ComputeValidatorsGroup1ValidatorShouldReturnSame(t *testing.T) { t.Parallel() @@ -558,7 +559,7 @@ func TestIndexHashedNodesCoordinator_ComputeValidatorsGroup400of400For10BlocksMe mut := sync.Mutex{} - //consensusGroup := list[0:21] + // consensusGroup := list[0:21] cacheMap := make(map[string]interface{}) lruCache := &mock.NodesCoordinatorCacheMock{ PutCalled: func(key []byte, value interface{}, sizeInBytes int) (evicted bool) { @@ -1275,7 +1276,7 @@ func TestIndexHashedNodesCoordinator_setNodesPerShardsShouldTriggerWrongConfigur }, } - err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2) + err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2, false) require.NoError(t, err) value := <-chanStopNode @@ -1301,7 +1302,7 @@ func TestIndexHashedNodesCoordinator_setNodesPerShardsShouldNotTriggerWrongConfi }, } - err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2) + err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2, false) require.NoError(t, err) require.Empty(t, chanStopNode) @@ -1333,7 +1334,7 @@ func TestIndexHashedNodesCoordinator_setNodesPerShardsShouldSetNodeTypeValidator }, } - err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2) + err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2, false) require.NoError(t, err) require.True(t, setTypeWasCalled) require.Equal(t, core.NodeTypeValidator, nodeTypeResult) @@ -1365,7 +1366,7 @@ func TestIndexHashedNodesCoordinator_setNodesPerShardsShouldSetNodeTypeObserver( }, } - err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2) + err = ihnc.setNodesPerShards(eligibleMap, map[uint32][]Validator{}, map[uint32][]Validator{}, map[uint32][]Validator{}, 2, false) require.NoError(t, err) require.True(t, setTypeWasCalled) require.Equal(t, core.NodeTypeObserver, nodeTypeResult) From 643030750d923256f74159f6f623964b03dc7c8e Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 15 May 2024 13:24:19 +0300 Subject: [PATCH 3/9] fix linter issues --- .../chainSimulator/staking/stake/stakeAndUnStake_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go index c29f5cab9b0..d876545a124 100644 --- a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go +++ b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go @@ -2452,6 +2452,8 @@ func TestChainSimulator_EdgeCaseLowWaitingList(t *testing.T) { // we always have 0 in auction list because of the lowWaitingList condition epochToCheck += 1 err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) + require.Nil(t, err) + numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) require.Equal(t, 0, numQualified) require.Equal(t, 0, numUnQualified) @@ -2461,6 +2463,8 @@ func TestChainSimulator_EdgeCaseLowWaitingList(t *testing.T) { epochToCheck += 1 err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) + require.Nil(t, err) + numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) // all the previously registered will be selected, as we have 24 nodes in eligible+waiting, 8 will shuffle out, // but this time there will be not be lowWaitingList, as there are enough in auction, so we will end up with From b9c087e984f393dfefcc6881b805f94b20f76962 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 15 May 2024 14:41:24 +0300 Subject: [PATCH 4/9] fix integration tests --- .../stakingProvider/delegation_test.go | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go b/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go index ad238766068..3ee5971a502 100644 --- a/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go +++ b/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go @@ -15,6 +15,10 @@ import ( "github.com/multiversx/mx-chain-crypto-go/signing" "github.com/multiversx/mx-chain-crypto-go/signing/mcl" mclsig "github.com/multiversx/mx-chain-crypto-go/signing/mcl/singlesig" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" chainSimulatorIntegrationTests "github.com/multiversx/mx-chain-go/integrationTests/chainSimulator" @@ -25,9 +29,6 @@ import ( chainSimulatorProcess "github.com/multiversx/mx-chain-go/node/chainSimulator/process" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/vm" - logger "github.com/multiversx/mx-chain-logger-go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) var log = logger.GetOrCreate("stakingProvider") @@ -399,11 +400,25 @@ func testBLSKeyIsInAuction( currentEpoch := metachainNode.GetCoreComponents().EnableEpochsHandler().GetCurrentEpoch() if metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step2Flag) == currentEpoch { // starting from phase 2, we have the shuffled out nodes from the previous epoch in the action list - actionListSize += 8 + // if there is no lowWaitingList condition + shuffledToAuctionValPubKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(currentEpoch) + require.Nil(t, err) + + if len(shuffledToAuctionValPubKeys) > 0 { + // there are 2 nodes per shard shuffled out so 2 * 4 = 8 + actionListSize += 8 + } } if metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step3Flag) <= currentEpoch { // starting from phase 3, we have the shuffled out nodes from the previous epoch in the action list - actionListSize += 4 + // if there is no lowWaitingList condition + shuffledToAuctionValPubKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(currentEpoch) + require.Nil(t, err) + + if len(shuffledToAuctionValPubKeys) > 0 { + // there are 2 nodes per shard shuffled out so 2 * 4 = 8 + actionListSize += 8 + } } require.Equal(t, actionListSize, len(auctionList)) From 3a877d975dadbf9e28faa53dfc3f9140506c0542 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 15 May 2024 14:46:01 +0300 Subject: [PATCH 5/9] simplify --- .../stakingProvider/delegation_test.go | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go b/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go index 3ee5971a502..da3950818b7 100644 --- a/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go +++ b/integrationTests/chainSimulator/staking/stakingProvider/delegation_test.go @@ -398,23 +398,15 @@ func testBLSKeyIsInAuction( require.Nil(t, err) currentEpoch := metachainNode.GetCoreComponents().EnableEpochsHandler().GetCurrentEpoch() - if metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step2Flag) == currentEpoch { - // starting from phase 2, we have the shuffled out nodes from the previous epoch in the action list - // if there is no lowWaitingList condition - shuffledToAuctionValPubKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(currentEpoch) - require.Nil(t, err) - if len(shuffledToAuctionValPubKeys) > 0 { - // there are 2 nodes per shard shuffled out so 2 * 4 = 8 - actionListSize += 8 - } - } - if metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step3Flag) <= currentEpoch { - // starting from phase 3, we have the shuffled out nodes from the previous epoch in the action list - // if there is no lowWaitingList condition - shuffledToAuctionValPubKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(currentEpoch) - require.Nil(t, err) + shuffledToAuctionValPubKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(currentEpoch) + require.Nil(t, err) + stakingV4Step2Epoch := metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step2Flag) + stakingV4Step3Epoch := metachainNode.GetCoreComponents().EnableEpochsHandler().GetActivationEpoch(common.StakingV4Step3Flag) + if stakingV4Step2Epoch == currentEpoch || stakingV4Step3Epoch == currentEpoch { + // starting from phase 2, we have the shuffled out nodes from the previous epoch in the action list + // if there is no lowWaitingList condition if len(shuffledToAuctionValPubKeys) > 0 { // there are 2 nodes per shard shuffled out so 2 * 4 = 8 actionListSize += 8 From 5e31461c03d4e602faef74d66c342b390b81c682 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 15 May 2024 15:27:05 +0300 Subject: [PATCH 6/9] simplify and add more constraints in integration test --- .../staking/stake/simpleStake_test.go | 21 ++--- .../staking/stake/stakeAndUnStake_test.go | 90 +++++++++++-------- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/integrationTests/chainSimulator/staking/stake/simpleStake_test.go b/integrationTests/chainSimulator/staking/stake/simpleStake_test.go index a4f63e44f28..9685ce78cc6 100644 --- a/integrationTests/chainSimulator/staking/stake/simpleStake_test.go +++ b/integrationTests/chainSimulator/staking/stake/simpleStake_test.go @@ -9,6 +9,8 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/integrationTests/chainSimulator/staking" @@ -17,7 +19,6 @@ import ( "github.com/multiversx/mx-chain-go/node/chainSimulator/configs" "github.com/multiversx/mx-chain-go/node/chainSimulator/process" "github.com/multiversx/mx-chain-go/vm" - "github.com/stretchr/testify/require" ) // Test scenarios @@ -261,30 +262,30 @@ func TestChainSimulator_StakingV4Step2APICalls(t *testing.T) { err = cs.GenerateBlocks(2) require.Nil(t, err) - numQualified, numUnQualified := getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 8, numQualified) - require.Equal(t, 1, numUnQualified) + qualified, unQualified := getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 8, len(qualified)) + require.Equal(t, 1, len(unQualified)) } } -func getNumQualifiedAndUnqualified(t *testing.T, metachainNode process.NodeHandler) (int, int) { +func getQualifiedAndUnqualifiedNodes(t *testing.T, metachainNode process.NodeHandler) ([]string, []string) { err := metachainNode.GetProcessComponents().ValidatorsProvider().ForceUpdate() require.Nil(t, err) auctionList, err := metachainNode.GetProcessComponents().ValidatorsProvider().GetAuctionList() require.Nil(t, err) - numQualified := 0 - numUnQualified := 0 + qualified := make([]string, 0) + unQualified := make([]string, 0) for _, auctionOwnerData := range auctionList { for _, auctionNode := range auctionOwnerData.Nodes { if auctionNode.Qualified { - numQualified++ + qualified = append(qualified, auctionNode.BlsKey) } else { - numUnQualified++ + unQualified = append(unQualified, auctionNode.BlsKey) } } } - return numQualified, numUnQualified + return qualified, unQualified } diff --git a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go index d876545a124..a46d800fe82 100644 --- a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go +++ b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go @@ -2367,21 +2367,21 @@ func TestChainSimulator_UnStakeOneActiveNodeAndCheckAPIAuctionList(t *testing.T) metachainNode := cs.GetNodeHandler(core.MetachainShardId) - numQualified, numUnQualified := getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 8, numQualified) - require.Equal(t, 0, numUnQualified) + qualified, unQualified := getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 8, len(qualified)) + require.Equal(t, 0, len(unQualified)) stakeOneNode(t, cs) - numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 8, numQualified) - require.Equal(t, 1, numUnQualified) + qualified, unQualified = getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 8, len(qualified)) + require.Equal(t, 1, len(unQualified)) unStakeOneActiveNode(t, cs) - numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 8, numQualified) - require.Equal(t, 1, numUnQualified) + qualified, unQualified = getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 8, len(qualified)) + require.Equal(t, 1, len(unQualified)) } // Nodes configuration at genesis consisting of a total of 40 nodes, distributed on 3 shards + meta: @@ -2445,58 +2445,75 @@ func TestChainSimulator_EdgeCaseLowWaitingList(t *testing.T) { require.Nil(t, err) metachainNode := cs.GetNodeHandler(core.MetachainShardId) - numQualified, numUnQualified := getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 0, numQualified) - require.Equal(t, 0, numUnQualified) + qualified, unQualified := getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 0, len(qualified)) + require.Equal(t, 0, len(unQualified)) // we always have 0 in auction list because of the lowWaitingList condition epochToCheck += 1 err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) require.Nil(t, err) - numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) - require.Equal(t, 0, numQualified) - require.Equal(t, 0, numUnQualified) + qualified, unQualified = getQualifiedAndUnqualifiedNodes(t, metachainNode) + require.Equal(t, 0, len(qualified)) + require.Equal(t, 0, len(unQualified)) // stake 16 mode nodes, these will go to auction list - stakeNodes(t, cs, 16) + stakeNodes(t, cs, 17) epochToCheck += 1 err = cs.GenerateBlocksUntilEpochIsReached(epochToCheck) require.Nil(t, err) - numQualified, numUnQualified = getNumQualifiedAndUnqualified(t, metachainNode) + qualified, unQualified = getQualifiedAndUnqualifiedNodes(t, metachainNode) // all the previously registered will be selected, as we have 24 nodes in eligible+waiting, 8 will shuffle out, // but this time there will be not be lowWaitingList, as there are enough in auction, so we will end up with // 24-8 = 16 nodes remaining + 16 from auction, to fill up all 32 positions - require.Equal(t, 16, numQualified) - require.Equal(t, 0, numUnQualified) -} + require.Equal(t, 16, len(qualified)) + require.Equal(t, 1, len(unQualified)) -func stakeNodes(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator, numTxs int) { - txs := make([]*transaction.Transaction, numTxs) - for i := 0; i < numTxs; i++ { - privateKey, blsKeys, err := chainSimulator.GenerateBlsPrivateKeys(1) - require.Nil(t, err) - err = cs.AddValidatorKeys(privateKey) - require.Nil(t, err) + shuffledOutNodesKeys, err := metachainNode.GetProcessComponents().NodesCoordinator().GetShuffledOutToAuctionValidatorsPublicKeys(uint32(epochToCheck)) + require.Nil(t, err) - mintValue := big.NewInt(0).Add(staking.MinimumStakeValue, staking.OneEGLD) - validatorOwner, err := cs.GenerateAndMintWalletAddress(core.AllShardId, mintValue) - require.Nil(t, err) + checkKeysNotInMap(t, shuffledOutNodesKeys, qualified) + checkKeysNotInMap(t, shuffledOutNodesKeys, unQualified) +} - txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature) - txs[i] = staking.GenerateTransaction(validatorOwner.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation) +func checkKeysNotInMap(t *testing.T, m map[uint32][][]byte, keys []string) { + for _, key := range keys { + for _, v := range m { + for _, k := range v { + mapKey := hex.EncodeToString(k) + require.NotEqual(t, key, mapKey) + } + } + } +} + +func stakeNodes(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator, numNodesToStake int) { + txs := make([]*transaction.Transaction, numNodesToStake) + for i := 0; i < numNodesToStake; i++ { + txs[i] = createStakeTransaction(t, cs) } + stakeTxs, err := cs.SendTxsAndGenerateBlocksTilAreExecuted(txs, staking.MaxNumOfBlockToGenerateWhenExecutingTx) require.Nil(t, err) require.NotNil(t, stakeTxs) - require.Len(t, stakeTxs, numTxs) + require.Len(t, stakeTxs, numNodesToStake) require.Nil(t, cs.GenerateBlocks(1)) } func stakeOneNode(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator) { + txStake := createStakeTransaction(t, cs) + stakeTx, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(txStake, staking.MaxNumOfBlockToGenerateWhenExecutingTx) + require.Nil(t, err) + require.NotNil(t, stakeTx) + + require.Nil(t, cs.GenerateBlocks(1)) +} + +func createStakeTransaction(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator) *transaction.Transaction { privateKey, blsKeys, err := chainSimulator.GenerateBlsPrivateKeys(1) require.Nil(t, err) err = cs.AddValidatorKeys(privateKey) @@ -2507,12 +2524,7 @@ func stakeOneNode(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator require.Nil(t, err) txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature) - txStake := staking.GenerateTransaction(validatorOwner.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation) - stakeTx, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(txStake, staking.MaxNumOfBlockToGenerateWhenExecutingTx) - require.Nil(t, err) - require.NotNil(t, stakeTx) - - require.Nil(t, cs.GenerateBlocks(1)) + return staking.GenerateTransaction(validatorOwner.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation) } func unStakeOneActiveNode(t *testing.T, cs chainSimulatorIntegrationTests.ChainSimulator) { From f2efedd51dc4d2aac1ee9f4073876a8bfb7f604d Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 17 May 2024 13:22:38 +0300 Subject: [PATCH 7/9] add epoch enable flag for cleanup --- cmd/node/config/enableEpochs.toml | 4 + common/constants.go | 1 + common/enablers/enableEpochsHandler.go | 9 ++- common/enablers/enableEpochsHandler_test.go | 9 ++- config/epochConfig.go | 1 + config/tomlConfig_test.go | 9 ++- .../staking/stake/stakeAndUnStake_test.go | 1 + .../nodesCoordinator/hashValidatorShuffler.go | 74 ++++++++++--------- .../indexHashedNodesCoordinatorRegistry.go | 3 +- 9 files changed, 71 insertions(+), 40 deletions(-) diff --git a/cmd/node/config/enableEpochs.toml b/cmd/node/config/enableEpochs.toml index d24e57df7e7..9502cceba9a 100644 --- a/cmd/node/config/enableEpochs.toml +++ b/cmd/node/config/enableEpochs.toml @@ -302,6 +302,10 @@ # StakingV4Step3EnableEpoch represents the epoch in which selected nodes from auction will be distributed to waiting list StakingV4Step3EnableEpoch = 3 + # CleanupAuctionOnLowWaitingListEnableEpoch represents the epoch when duplicated data cleanup from auction list is enabled in the condition of a low waiting list + # Should have the same value as StakingV4Step1EnableEpoch if the low waiting list has not happened, otherwise should have a greater value + CleanupAuctionOnLowWaitingListEnableEpoch = 1 + # AlwaysMergeContextsInEEIEnableEpoch represents the epoch in which the EEI will always merge the contexts AlwaysMergeContextsInEEIEnableEpoch = 1 diff --git a/common/constants.go b/common/constants.go index 16c77a5d147..5320ee675c1 100644 --- a/common/constants.go +++ b/common/constants.go @@ -1011,6 +1011,7 @@ const ( StakingV4Step1Flag core.EnableEpochFlag = "StakingV4Step1Flag" StakingV4Step2Flag core.EnableEpochFlag = "StakingV4Step2Flag" StakingV4Step3Flag core.EnableEpochFlag = "StakingV4Step3Flag" + CleanupAuctionOnLowWaitingListFlag core.EnableEpochFlag = "CleanupAuctionOnLowWaitingListFlag" StakingV4StartedFlag core.EnableEpochFlag = "StakingV4StartedFlag" AlwaysMergeContextsInEEIFlag core.EnableEpochFlag = "AlwaysMergeContextsInEEIFlag" // all new flags must be added to createAllFlagsMap method, as part of enableEpochsHandler allFlagsDefined diff --git a/common/enablers/enableEpochsHandler.go b/common/enablers/enableEpochsHandler.go index f64dbf99ea5..5ce3812742f 100644 --- a/common/enablers/enableEpochsHandler.go +++ b/common/enablers/enableEpochsHandler.go @@ -6,10 +6,11 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/process" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("common/enablers") @@ -713,6 +714,12 @@ func (handler *enableEpochsHandler) createAllFlagsMap() { }, activationEpoch: handler.enableEpochsConfig.StakingV4Step3EnableEpoch, }, + common.CleanupAuctionOnLowWaitingListFlag: { + isActiveInEpoch: func(epoch uint32) bool { + return epoch >= handler.enableEpochsConfig.CleanupAuctionOnLowWaitingListEnableEpoch + }, + activationEpoch: handler.enableEpochsConfig.CleanupAuctionOnLowWaitingListEnableEpoch, + }, common.StakingV4StartedFlag: { isActiveInEpoch: func(epoch uint32) bool { return epoch >= handler.enableEpochsConfig.StakingV4Step1EnableEpoch diff --git a/common/enablers/enableEpochsHandler_test.go b/common/enablers/enableEpochsHandler_test.go index 4155b15dfbb..2c568f2043b 100644 --- a/common/enablers/enableEpochsHandler_test.go +++ b/common/enablers/enableEpochsHandler_test.go @@ -5,13 +5,14 @@ import ( "testing" "github.com/multiversx/mx-chain-core-go/core/check" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/testscommon/epochNotifier" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func createEnableEpochsConfig() config.EnableEpochs { @@ -113,6 +114,7 @@ func createEnableEpochsConfig() config.EnableEpochs { StakingV4Step1EnableEpoch: 96, StakingV4Step2EnableEpoch: 97, StakingV4Step3EnableEpoch: 98, + CleanupAuctionOnLowWaitingListEnableEpoch: 96, AlwaysMergeContextsInEEIEnableEpoch: 99, } } @@ -426,6 +428,7 @@ func TestEnableEpochsHandler_GetActivationEpoch(t *testing.T) { require.Equal(t, cfg.StakingV4Step1EnableEpoch, handler.GetActivationEpoch(common.StakingV4Step1Flag)) require.Equal(t, cfg.StakingV4Step2EnableEpoch, handler.GetActivationEpoch(common.StakingV4Step2Flag)) require.Equal(t, cfg.StakingV4Step3EnableEpoch, handler.GetActivationEpoch(common.StakingV4Step3Flag)) + require.Equal(t, cfg.CleanupAuctionOnLowWaitingListEnableEpoch, handler.GetActivationEpoch(common.CleanupAuctionOnLowWaitingListFlag)) require.Equal(t, cfg.StakingV4Step1EnableEpoch, handler.GetActivationEpoch(common.StakingV4StartedFlag)) require.Equal(t, cfg.AlwaysMergeContextsInEEIEnableEpoch, handler.GetActivationEpoch(common.AlwaysMergeContextsInEEIFlag)) } diff --git a/config/epochConfig.go b/config/epochConfig.go index 7789ecc72b3..764970ae050 100644 --- a/config/epochConfig.go +++ b/config/epochConfig.go @@ -112,6 +112,7 @@ type EnableEpochs struct { StakingV4Step1EnableEpoch uint32 StakingV4Step2EnableEpoch uint32 StakingV4Step3EnableEpoch uint32 + CleanupAuctionOnLowWaitingListEnableEpoch uint32 AlwaysMergeContextsInEEIEnableEpoch uint32 BLSMultiSignerEnableEpoch []MultiSignerConfig } diff --git a/config/tomlConfig_test.go b/config/tomlConfig_test.go index 45dd2c7ef00..84d0a7ecb57 100644 --- a/config/tomlConfig_test.go +++ b/config/tomlConfig_test.go @@ -5,10 +5,11 @@ import ( "strconv" "testing" - p2pConfig "github.com/multiversx/mx-chain-go/p2p/config" "github.com/pelletier/go-toml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + p2pConfig "github.com/multiversx/mx-chain-go/p2p/config" ) func TestTomlParser(t *testing.T) { @@ -839,10 +840,13 @@ func TestEnableEpochConfig(t *testing.T) { # CurrentRandomnessOnSortingEnableEpoch represents the epoch when the current randomness on sorting is enabled CurrentRandomnessOnSortingEnableEpoch = 93 - + # AlwaysMergeContextsInEEIEnableEpoch represents the epoch in which the EEI will always merge the contexts AlwaysMergeContextsInEEIEnableEpoch = 94 + # CleanupAuctionOnLowWaitingListEnableEpoch represents the epoch when the cleanup auction on low waiting list is enabled + CleanupAuctionOnLowWaitingListEnableEpoch = 95 + # MaxNodesChangeEnableEpoch holds configuration for changing the maximum number of nodes and the enabling epoch MaxNodesChangeEnableEpoch = [ { EpochEnable = 44, MaxNumNodes = 2169, NodesToShufflePerShard = 80 }, @@ -955,6 +959,7 @@ func TestEnableEpochConfig(t *testing.T) { MigrateDataTrieEnableEpoch: 92, CurrentRandomnessOnSortingEnableEpoch: 93, AlwaysMergeContextsInEEIEnableEpoch: 94, + CleanupAuctionOnLowWaitingListEnableEpoch: 95, MaxNodesChangeEnableEpoch: []MaxNodesChangeConfig{ { EpochEnable: 44, diff --git a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go index a46d800fe82..b3a1f1b7d4f 100644 --- a/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go +++ b/integrationTests/chainSimulator/staking/stake/stakeAndUnStake_test.go @@ -2348,6 +2348,7 @@ func TestChainSimulator_UnStakeOneActiveNodeAndCheckAPIAuctionList(t *testing.T) cfg.EpochConfig.EnableEpochs.StakingV4Step1EnableEpoch = stakingV4Step1Epoch cfg.EpochConfig.EnableEpochs.StakingV4Step2EnableEpoch = stakingV4Step2Epoch cfg.EpochConfig.EnableEpochs.StakingV4Step3EnableEpoch = stakingV4Step3Epoch + cfg.EpochConfig.EnableEpochs.CleanupAuctionOnLowWaitingListEnableEpoch = stakingV4Step1Epoch cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[1].MaxNumNodes = 32 cfg.EpochConfig.EnableEpochs.MaxNodesChangeEnableEpoch[1].NodesToShufflePerShard = 2 diff --git a/sharding/nodesCoordinator/hashValidatorShuffler.go b/sharding/nodesCoordinator/hashValidatorShuffler.go index 7c54e132ffc..71d2b5351b3 100644 --- a/sharding/nodesCoordinator/hashValidatorShuffler.go +++ b/sharding/nodesCoordinator/hashValidatorShuffler.go @@ -31,22 +31,23 @@ type NodesShufflerArgs struct { } type shuffleNodesArg struct { - eligible map[uint32][]Validator - waiting map[uint32][]Validator - unstakeLeaving []Validator - additionalLeaving []Validator - newNodes []Validator - auction []Validator - randomness []byte - distributor ValidatorsDistributor - nodesMeta uint32 - nodesPerShard uint32 - nbShards uint32 - maxNodesToSwapPerShard uint32 - maxNumNodes uint32 - flagBalanceWaitingLists bool - flagStakingV4Step2 bool - flagStakingV4Step3 bool + eligible map[uint32][]Validator + waiting map[uint32][]Validator + unstakeLeaving []Validator + additionalLeaving []Validator + newNodes []Validator + auction []Validator + randomness []byte + distributor ValidatorsDistributor + nodesMeta uint32 + nodesPerShard uint32 + nbShards uint32 + maxNodesToSwapPerShard uint32 + maxNumNodes uint32 + flagBalanceWaitingLists bool + flagStakingV4Step2 bool + flagStakingV4Step3 bool + flagCleanupAuctionOnLowWaitingList bool } type shuffledNodesConfig struct { @@ -91,6 +92,7 @@ func NewHashValidatorsShuffler(args *NodesShufflerArgs) (*randHashShuffler, erro } err := core.CheckHandlerCompatibility(args.EnableEpochsHandler, []core.EnableEpochFlag{ common.BalanceWaitingListsFlag, + common.CleanupAuctionOnLowWaitingListFlag, }) if err != nil { return nil, err @@ -197,22 +199,23 @@ func (rhs *randHashShuffler) UpdateNodeLists(args ArgsUpdateNodes) (*ResUpdateNo } return shuffleNodes(shuffleNodesArg{ - eligible: eligibleAfterReshard, - waiting: waitingAfterReshard, - unstakeLeaving: args.UnStakeLeaving, - additionalLeaving: args.AdditionalLeaving, - newNodes: args.NewNodes, - auction: args.Auction, - randomness: args.Rand, - nodesMeta: nodesMeta, - nodesPerShard: nodesPerShard, - nbShards: args.NbShards, - distributor: rhs.validatorDistributor, - maxNodesToSwapPerShard: rhs.activeNodesConfig.NodesToShufflePerShard, - flagBalanceWaitingLists: rhs.enableEpochsHandler.IsFlagEnabledInEpoch(common.BalanceWaitingListsFlag, args.Epoch), - flagStakingV4Step2: rhs.flagStakingV4Step2.IsSet(), - flagStakingV4Step3: rhs.flagStakingV4Step3.IsSet(), - maxNumNodes: rhs.activeNodesConfig.MaxNumNodes, + eligible: eligibleAfterReshard, + waiting: waitingAfterReshard, + unstakeLeaving: args.UnStakeLeaving, + additionalLeaving: args.AdditionalLeaving, + newNodes: args.NewNodes, + auction: args.Auction, + randomness: args.Rand, + nodesMeta: nodesMeta, + nodesPerShard: nodesPerShard, + nbShards: args.NbShards, + distributor: rhs.validatorDistributor, + maxNodesToSwapPerShard: rhs.activeNodesConfig.NodesToShufflePerShard, + flagBalanceWaitingLists: rhs.enableEpochsHandler.IsFlagEnabledInEpoch(common.BalanceWaitingListsFlag, args.Epoch), + flagStakingV4Step2: rhs.flagStakingV4Step2.IsSet(), + flagStakingV4Step3: rhs.flagStakingV4Step3.IsSet(), + maxNumNodes: rhs.activeNodesConfig.MaxNumNodes, + flagCleanupAuctionOnLowWaitingList: rhs.enableEpochsHandler.IsFlagEnabledInEpoch(common.CleanupAuctionOnLowWaitingListFlag, args.Epoch), }) } @@ -345,13 +348,18 @@ func shuffleNodes(arg shuffleNodesArg) (*ResUpdateNodes, error) { actualLeaving, _ := removeValidatorsFromList(allLeaving, stillRemainingInLeaving, len(stillRemainingInLeaving)) + shouldCleanupAuction := false + if arg.flagCleanupAuctionOnLowWaitingList { + shouldCleanupAuction = lowWaitingList + } + return &ResUpdateNodes{ Eligible: newEligible, Waiting: newWaiting, ShuffledOut: shuffledOutMap, Leaving: actualLeaving, StillRemaining: stillRemainingInLeaving, - LowWaitingList: lowWaitingList, + LowWaitingList: shouldCleanupAuction, }, nil } diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry.go b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry.go index 813929bac90..55cbb326753 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry.go @@ -61,7 +61,7 @@ func displayNodesConfigInfo(config map[uint32]*epochNodesConfig) { func (ihnc *indexHashedNodesCoordinator) saveState(key []byte, epoch uint32) error { registry := ihnc.NodesCoordinatorToRegistry(epoch) - data, err := ihnc.nodesCoordinatorRegistryFactory.GetRegistryData(registry, ihnc.currentEpoch) + data, err := ihnc.nodesCoordinatorRegistryFactory.GetRegistryData(registry, epoch) if err != nil { return err } @@ -212,6 +212,7 @@ func epochValidatorsToEpochNodesConfig(config EpochValidatorsHandler) (*epochNod if err != nil { return nil, err } + result.lowWaitingList = configWithAuction.GetLowWaitingList() } return result, nil From 1dd6e0755e3d063447980f2e61d41d28c83ff34e Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 17 May 2024 13:23:02 +0300 Subject: [PATCH 8/9] fix restore from registry --- ...ndexHashedNodesCoordinatorRegistry_test.go | 34 +++++++++++++++++-- sharding/nodesCoordinator/interface.go | 1 + .../nodesCoordinatorRegistryFactory.go | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry_test.go b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry_test.go index b2b99e6e87b..0a91ba9170a 100644 --- a/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry_test.go +++ b/sharding/nodesCoordinator/indexHashedNodesCoordinatorRegistry_test.go @@ -7,10 +7,11 @@ import ( "testing" "github.com/multiversx/mx-chain-core-go/core" - "github.com/multiversx/mx-chain-go/common" - "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/multiversx/mx-chain-go/common" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" ) func sameValidatorsMaps(map1, map2 map[uint32][]Validator) bool { @@ -174,6 +175,35 @@ func TestIndexHashedNodesCoordinator_nodesCoordinatorToRegistry(t *testing.T) { } } +func TestIndexHashedNodesCoordinator_nodesCoordinatorWithAuctionToRegistryAndBack(t *testing.T) { + args := createArguments() + nodesCoordinator, _ := NewIndexHashedNodesCoordinator(args) + + nodesConfigForEpoch := nodesCoordinator.nodesConfig[args.Epoch] + nodesConfigForEpoch.shuffledOutMap = createDummyNodesMap(3, 0, string(common.WaitingList)) + nodesConfigForEpoch.lowWaitingList = true + // leave only one epoch config in nc + nodesCoordinator.nodesConfig = make(map[uint32]*epochNodesConfig) + nodesCoordinator.nodesConfig[args.Epoch] = nodesConfigForEpoch + + ncr := nodesCoordinator.nodesCoordinatorToRegistryWithAuction() + require.True(t, sameValidatorsDifferentMapTypes(nodesConfigForEpoch.eligibleMap, ncr.GetEpochsConfig()[fmt.Sprint(args.Epoch)].GetEligibleValidators())) + require.True(t, sameValidatorsDifferentMapTypes(nodesConfigForEpoch.waitingMap, ncr.GetEpochsConfig()[fmt.Sprint(args.Epoch)].GetWaitingValidators())) + require.True(t, sameValidatorsDifferentMapTypes(nodesConfigForEpoch.shuffledOutMap, ncr.GetEpochsConfigWithAuction()[fmt.Sprint(args.Epoch)].GetShuffledOutValidators())) + require.Equal(t, nodesConfigForEpoch.lowWaitingList, ncr.GetEpochsConfigWithAuction()[fmt.Sprint(args.Epoch)].GetLowWaitingList()) + + nodesConfig, err := nodesCoordinator.registryToNodesCoordinator(ncr) + require.Nil(t, err) + + assert.Equal(t, len(nodesCoordinator.nodesConfig), len(nodesConfig)) + for epoch, config := range nodesCoordinator.nodesConfig { + require.True(t, sameValidatorsMaps(config.eligibleMap, nodesConfig[epoch].eligibleMap)) + require.True(t, sameValidatorsMaps(config.waitingMap, nodesConfig[epoch].waitingMap)) + require.True(t, sameValidatorsMaps(config.shuffledOutMap, nodesConfig[epoch].shuffledOutMap)) + require.Equal(t, config.lowWaitingList, nodesConfig[epoch].lowWaitingList) + } +} + func TestIndexHashedNodesCoordinator_registryToNodesCoordinator(t *testing.T) { args := createArguments() nodesCoordinator1, _ := NewIndexHashedNodesCoordinator(args) diff --git a/sharding/nodesCoordinator/interface.go b/sharding/nodesCoordinator/interface.go index b962c6fa50a..5e2d5564a5c 100644 --- a/sharding/nodesCoordinator/interface.go +++ b/sharding/nodesCoordinator/interface.go @@ -154,6 +154,7 @@ type EpochValidatorsHandler interface { type EpochValidatorsHandlerWithAuction interface { EpochValidatorsHandler GetShuffledOutValidators() map[string][]*SerializableValidator + GetLowWaitingList() bool } // NodesCoordinatorRegistryHandler defines what is used to initialize nodes coordinator diff --git a/sharding/nodesCoordinator/nodesCoordinatorRegistryFactory.go b/sharding/nodesCoordinator/nodesCoordinatorRegistryFactory.go index 0ef508fbf89..894d3f7a1f0 100644 --- a/sharding/nodesCoordinator/nodesCoordinatorRegistryFactory.go +++ b/sharding/nodesCoordinator/nodesCoordinatorRegistryFactory.go @@ -49,7 +49,7 @@ func (ncf *nodesCoordinatorRegistryFactory) createRegistryWithAuction(buff []byt return nil, err } - log.Debug("nodesCoordinatorRegistryFactory.CreateNodesCoordinatorRegistry created old registry", + log.Debug("nodesCoordinatorRegistryFactory.CreateNodesCoordinatorRegistry created registry with auction", "epoch", registry.CurrentEpoch) return registry, nil } From 8968d5cfaf04fe8883ecd86b268beaa1f03ba103 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 17 May 2024 14:18:19 +0300 Subject: [PATCH 9/9] fix alignment --- config/tomlConfig_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/tomlConfig_test.go b/config/tomlConfig_test.go index 84d0a7ecb57..eaeb4e6e2ae 100644 --- a/config/tomlConfig_test.go +++ b/config/tomlConfig_test.go @@ -840,12 +840,12 @@ func TestEnableEpochConfig(t *testing.T) { # CurrentRandomnessOnSortingEnableEpoch represents the epoch when the current randomness on sorting is enabled CurrentRandomnessOnSortingEnableEpoch = 93 - + # AlwaysMergeContextsInEEIEnableEpoch represents the epoch in which the EEI will always merge the contexts AlwaysMergeContextsInEEIEnableEpoch = 94 - # CleanupAuctionOnLowWaitingListEnableEpoch represents the epoch when the cleanup auction on low waiting list is enabled - CleanupAuctionOnLowWaitingListEnableEpoch = 95 + # CleanupAuctionOnLowWaitingListEnableEpoch represents the epoch when the cleanup auction on low waiting list is enabled + CleanupAuctionOnLowWaitingListEnableEpoch = 95 # MaxNodesChangeEnableEpoch holds configuration for changing the maximum number of nodes and the enabling epoch MaxNodesChangeEnableEpoch = [