diff --git a/epochStart/metachain/legacySystemSCs.go b/epochStart/metachain/legacySystemSCs.go index 327a5ab88e5..02107c1c950 100644 --- a/epochStart/metachain/legacySystemSCs.go +++ b/epochStart/metachain/legacySystemSCs.go @@ -14,6 +14,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" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/errChan" vInfo "github.com/multiversx/mx-chain-go/common/validatorInfo" @@ -24,7 +26,6 @@ import ( "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/vm" "github.com/multiversx/mx-chain-go/vm/systemSmartContracts" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) type legacySystemSCProcessor struct { @@ -288,12 +289,11 @@ func (s *legacySystemSCProcessor) unStakeNodesWithNotEnoughFunds( continue } + stakingV4Enabled := s.enableEpochsHandler.IsFlagEnabled(common.StakingV4StartedFlag) validatorLeaving := validatorInfo.ShallowClone() - validatorLeaving.SetListAndIndex(string(common.LeavingList), validatorLeaving.GetIndex(), s.enableEpochsHandler.IsFlagEnabled(common.StakingV4StartedFlag)) - err = validatorsInfoMap.Replace(validatorInfo, validatorLeaving) - if err != nil { - return 0, err - } + validatorLeaving.SetListAndIndex(string(common.LeavingList), validatorLeaving.GetIndex(), stakingV4Enabled) + err = s.replaceValidators(validatorInfo, validatorLeaving, validatorsInfoMap) + log.LogIfError(err) } err = s.updateDelegationContracts(mapOwnersKeys) @@ -302,7 +302,9 @@ func (s *legacySystemSCProcessor) unStakeNodesWithNotEnoughFunds( } nodesToStakeFromQueue := uint32(len(nodesToUnStake)) - nodesToStakeFromQueue -= nodesUnStakedFromAdditionalQueue + if s.enableEpochsHandler.IsFlagEnabled(common.CorrectLastUnJailedFlag) { + nodesToStakeFromQueue -= nodesUnStakedFromAdditionalQueue + } log.Debug("stake nodes from waiting list", "num", nodesToStakeFromQueue) return nodesToStakeFromQueue, nil @@ -720,10 +722,8 @@ func (s *legacySystemSCProcessor) stakingToValidatorStatistics( } if !isNew { - err = validatorsInfoMap.Delete(jailedValidator) - if err != nil { - return nil, err - } + // the new validator is deleted from the staking queue, not the jailed validator + validatorsInfoMap.DeleteByKey(blsPubKey, account.GetShardId()) } account.SetListAndIndex(jailedValidator.GetShardId(), string(common.NewList), uint32(stakingData.StakedNonce), s.enableEpochsHandler.IsFlagEnabled(common.StakingV4StartedFlag)) @@ -752,14 +752,26 @@ func (s *legacySystemSCProcessor) stakingToValidatorStatistics( } newValidatorInfo := s.validatorInfoCreator.PeerAccountToValidatorInfo(account) - err = validatorsInfoMap.Replace(jailedValidator, newValidatorInfo) - if err != nil { - return nil, err - } + err = s.replaceValidators(jailedValidator, newValidatorInfo, validatorsInfoMap) + log.LogIfError(err) return blsPubKey, nil } +func (s *legacySystemSCProcessor) replaceValidators( + old state.ValidatorInfoHandler, + new state.ValidatorInfoHandler, + validatorsInfoMap state.ShardValidatorsInfoMapHandler, +) error { + stakingV4Enabled := s.enableEpochsHandler.IsFlagEnabled(common.StakingV4StartedFlag) + if stakingV4Enabled { + return validatorsInfoMap.Replace(old, new) + } + + _ = validatorsInfoMap.ReplaceValidatorByKey(old.GetPublicKey(), new, old.GetShardId()) + return nil +} + func isValidator(validator state.ValidatorInfoHandler) bool { return validator.GetList() == string(common.WaitingList) || validator.GetList() == string(common.EligibleList) } diff --git a/state/interface.go b/state/interface.go index bf515803346..8a8c18a18c7 100644 --- a/state/interface.go +++ b/state/interface.go @@ -6,8 +6,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/api" - "github.com/multiversx/mx-chain-go/common" vmcommon "github.com/multiversx/mx-chain-vm-common-go" + + "github.com/multiversx/mx-chain-go/common" ) // AccountFactory creates an account of different types @@ -292,7 +293,9 @@ type ShardValidatorsInfoMapHandler interface { Add(validator ValidatorInfoHandler) error Delete(validator ValidatorInfoHandler) error + DeleteByKey(blsKey []byte, shardID uint32) Replace(old ValidatorInfoHandler, new ValidatorInfoHandler) error + ReplaceValidatorByKey(oldBlsKey []byte, new ValidatorInfoHandler, shardID uint32) bool SetValidatorsInShard(shardID uint32, validators []ValidatorInfoHandler) error } diff --git a/state/validatorsInfoMap.go b/state/validatorsInfoMap.go index e6c492d9d39..9069bf4a01d 100644 --- a/state/validatorsInfoMap.go +++ b/state/validatorsInfoMap.go @@ -106,14 +106,9 @@ func (vi *shardValidatorsInfoMap) Replace(old ValidatorInfoHandler, new Validato "with new validator", hex.EncodeToString(new.GetPublicKey()), "shard", new.GetShardId(), "list", new.GetList(), ) - vi.mutex.Lock() - defer vi.mutex.Unlock() - - for idx, validator := range vi.valInfoMap[shardID] { - if bytes.Equal(validator.GetPublicKey(), old.GetPublicKey()) { - vi.valInfoMap[shardID][idx] = new - return nil - } + replaced := vi.ReplaceValidatorByKey(old.GetPublicKey(), new, shardID) + if replaced { + return nil } return fmt.Errorf("old %w: %s when trying to replace it with %s", @@ -123,6 +118,20 @@ func (vi *shardValidatorsInfoMap) Replace(old ValidatorInfoHandler, new Validato ) } +// ReplaceValidatorByKey will replace an existing ValidatorInfoHandler with a new one, based on the provided blsKey for the old record. +func (vi *shardValidatorsInfoMap) ReplaceValidatorByKey(oldBlsKey []byte, new ValidatorInfoHandler, shardID uint32) bool { + vi.mutex.Lock() + defer vi.mutex.Unlock() + + for idx, validator := range vi.valInfoMap[shardID] { + if bytes.Equal(validator.GetPublicKey(), oldBlsKey) { + vi.valInfoMap[shardID][idx] = new + return true + } + } + return false +} + // SetValidatorsInShard resets all validators saved in a specific shard with the provided []ValidatorInfoHandler. // Before setting them, it checks that provided validators have the same shardID as the one provided. func (vi *shardValidatorsInfoMap) SetValidatorsInShard(shardID uint32, validators []ValidatorInfoHandler) error { @@ -160,11 +169,17 @@ func (vi *shardValidatorsInfoMap) Delete(validator ValidatorInfoHandler) error { } shardID := validator.GetShardId() + vi.DeleteByKey(validator.GetPublicKey(), shardID) + return nil +} + +// DeleteByKey will delete the provided blsKey from the internally stored map, if found. +func (vi *shardValidatorsInfoMap) DeleteByKey(blsKey []byte, shardID uint32) { vi.mutex.Lock() defer vi.mutex.Unlock() for index, validatorInfo := range vi.valInfoMap[shardID] { - if bytes.Equal(validatorInfo.GetPublicKey(), validator.GetPublicKey()) { + if bytes.Equal(validatorInfo.GetPublicKey(), blsKey) { length := len(vi.valInfoMap[shardID]) vi.valInfoMap[shardID][index] = vi.valInfoMap[shardID][length-1] vi.valInfoMap[shardID][length-1] = nil @@ -172,6 +187,4 @@ func (vi *shardValidatorsInfoMap) Delete(validator ValidatorInfoHandler) error { break } } - - return nil } diff --git a/vm/systemSmartContracts/eei.go b/vm/systemSmartContracts/eei.go index 3f251a6cca4..55f554d11b0 100644 --- a/vm/systemSmartContracts/eei.go +++ b/vm/systemSmartContracts/eei.go @@ -144,8 +144,6 @@ func (host *vmContext) GetStorageFromAddress(address []byte, key []byte) []byte if value, isInMap := storageAdrMap[string(key)]; isInMap { return value } - } else { - storageAdrMap = make(map[string][]byte) } data, _, err := host.blockChainHook.GetStorageData(address, key) @@ -153,8 +151,6 @@ func (host *vmContext) GetStorageFromAddress(address []byte, key []byte) []byte return nil } - storageAdrMap[string(key)] = data - return data }