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

Filter auction nodes list #3822

Merged
merged 26 commits into from Mar 9, 2022

Conversation

mariusmihaic
Copy link
Contributor

@mariusmihaic mariusmihaic commented Feb 21, 2022

Staking v4 nodes filtering

  • All nodes which are in the auction list will be sorted based on their top up per node. If >= 2 bls keys have the same top up, they will be sorted based on XOR with previous block rand seed. The number of available node slots will be computed and only the first nodes in the sorted auction list will fill these slots.
  • Added a display func to see the whole auction list and all nodes which will be moved to new list (to be further used by nodes coordinator to select them as eligible), e.g. from an auction of 5 bls keys, only 3 will be selected (pubKey2, pubKey9, pubKey4):
		+--------+----------------+----------------+
		| Owner  | Registered key | TopUp per node |
		+--------+----------------+----------------+
		| owner1 | pubKey2        | 1000           |
		| owner4 | pubKey9        | 500            |
		| owner2 | pubKey4        | 0              |
		+--------+----------------+----------------+
		| owner2 | pubKey5        | 0              |
		| owner3 | pubKey7        | 0              |
		+--------+----------------+----------------+

Refactor

  • In stakingDataProvider.go, refactored GetBlsKeyOwner to be an exported func
  • In systemSCs_test refactored test funcs which added validator data and staking data, so that we can easily register an owner and its staked bls keys and top up per node
  • ProcessSystemSmartContract from EpochStartSystemSCProcessor interface to accept an extra param: randomness []byte for sorting bls keys

@mariusmihaic mariusmihaic changed the title FEAT: Add first ugly version Filter auction nodes list Feb 21, 2022
@mariusmihaic mariusmihaic self-assigned this Feb 21, 2022
@mariusmihaic mariusmihaic marked this pull request as ready for review March 1, 2022 06:38
@iulianpascalau iulianpascalau self-requested a review March 1, 2022 11:08
Copy link
Contributor

@iulianpascalau iulianpascalau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! 👍
Some findings that will improve performance

cmd/node/config/enableEpochs.toml Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs.go Show resolved Hide resolved
epochStart/metachain/systemSCs.go Show resolved Hide resolved
epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
epochStart/metachain/systemSCs_test.go Show resolved Hide resolved
epochStart/metachain/systemSCs_test.go Show resolved Hide resolved
iulianpascalau
iulianpascalau previously approved these changes Mar 1, 2022
@@ -191,6 +191,9 @@
# all nodes from staking queue are moved in the auction list
StakingV4InitEnableEpoch = 4

# StakingV4EnableEpoch represents the epoch when staking v4 is enabled. Should have a greater value than StakingV4InitEnableEpoch
StakingV4EnableEpoch = 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this should always be StakingV4InitEnableEpoch + 1? What happens if we wrongly configure this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically, code should not panic or anything. If EnableEpoch < InitEpoch => auction list will be empty => no sorting/selection will be made.
Logic-wise, if they are inverted it shouldn't cause any bugs for NOW. I'm not sure how the implementation on nodes coordinator side will look like to give an educated opinion. Depending how it will be designed, it might cause some bugs

Base automatically changed from EN-11661-staking-v4-init to feat/liquid-staking March 2, 2022 13:45
@@ -214,6 +220,7 @@ func (s *systemSCProcessor) ProcessSystemSmartContract(
validatorInfos map[uint32][]*state.ValidatorInfo,
nonce uint64,
epoch uint32,
randomness []byte,
) error {
if s.flagHystNodesEnabled.IsSet() {
err := s.updateSystemSCConfigMinNodes()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need a sort of refactor here - like adding a separate function with old / inactive flags - all those things which were once activated on the mainnet. That we we make it easier to read this function. like flagHystNodes, flagSetOwner, flagChangeMaxNodes, flagCorrectlastUnJailed, flagDelegationEnabled, flagCorrectNumNodesToStake

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are called only once - so you could add flagESDTEnabled there. Move to new activation function which are not yet enabled, like flagGovernance, flagBuiltInOnMetachain, flagStakingV4Init

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to split them in 2 functions with pretty "trivial" names:

  • checkOldFlags (which contains: flagHystNodes, flagSetOwner,...)
  • checkNewFlags(which contains flagGovernance, flagStakingV4Init,...)

epochStart/metachain/systemSCs.go Show resolved Hide resolved
@@ -403,7 +403,7 @@ func (mp *metaProcessor) processEpochStartMetaBlock(
}

if mp.isRewardsV2Enabled(header) {
err = mp.epochSystemSCProcessor.ProcessSystemSmartContract(allValidatorsInfo, header.Nonce, header.Epoch)
err = mp.epochSystemSCProcessor.ProcessSystemSmartContract(allValidatorsInfo, header.Nonce, header.Epoch, header.GetPrevRandSeed())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be better to send the whole header. instead of 3 arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably in this case would be better; since maybe in the future we might need additional data from header;
Will refactor it

}

auctionListSize := uint32(len(auctionList))
numOfAvailableNodeSlots := core.MinUint32(auctionListSize, s.maxNodes-numOfValidators)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make a check on numValidators < s.maxNodes -> return -> do not do anything - it means there are not enough nodes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still add the sanity check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added sanity check as an early exit point

return compareByXORWithRandomness(pubKey1, pubKey2, randomness)
}

return nodeTopUpPubKey1.Cmp(nodeTopUpPubKey2) == 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 instead of == 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 0?

We want to compare which node has the highest top up. Cmp documentation says:

// Cmp compares x and y and returns:
//
//   -1 if x <  y
//    0 if x == y
//   +1 if x >  y

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use bigger than 0. like ">0"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to >0

s.displayAuctionList(auctionList, numOfAvailableNodeSlots)

for i := uint32(0); i < numOfAvailableNodeSlots; i++ {
auctionList[i].List = string(common.NewList)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to somewhat rewrite the map[uint32][]*state.ValidatorInfo - like use an interface and set new values there. It is ok for now - but it is super easy to make a mistake - modifying a value under a wrong pointer - hard to catch. Add a task for this rework.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, current implementation it is pretty prone to errors; however I'm not sure how this interface might look like -> seems a bit of overhead; will add a TODO

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add Jira task as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add task in Jira as well


for _, validator := range validators {
pubKey := validator.PublicKey
topUp, err := s.stakingDataProvider.GetNodeStakedTopUp(pubKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discussion is needed here in order to see if we want the following: one entity might register 10 nodes with 3000eGLD, meaning 500 topup per node. but if the topUp limit is at 2500 - that entity might have 5 nodes which enter and 5 which will not. However the first auction system was designed like that - selecting the most possible for an account. So add a task for this - let's discuss and it should be another task if we decide that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will leave this topic open and create a new Jira task

validatorsInfoMap map[uint32][]*state.ValidatorInfo,
header data.HeaderHandler,
) error {
err := s.checkOldFlags(validatorsInfoMap, header.GetNonce(), header.GetEpoch())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename processingWithOldFlags

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it

epochStart/metachain/systemSCs.go Outdated Show resolved Hide resolved
if err != nil {
return err
}
}

if s.flagStakingV2Enabled.IsSet() {
err := s.prepareRewardsData(validatorInfos)
numUnStaked, err := s.prepareStakingAndUnStakeNodesWithNotEnoughFunds(validatorsInfoMap, epoch)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please leave functions as it was.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and make completely new functions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored this code

return err
func (s *systemSCProcessor) prepareStakingData(validatorsInfoMap map[uint32][]*state.ValidatorInfo) error {
nodes := make(map[uint32][][]byte)
if s.flagStakingV2Enabled.IsSet() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no 2 flags on the same function. it is better to have duplicated code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored it so we don't have 2 flags

common/constants.go Show resolved Hide resolved
if err != nil {
return err
}

numUnStaked, err := s.unStakeNodesWithNotEnoughFunds(validatorInfos, epoch)
err = s.stakeNodesFromQueue(validatorsInfoMap, numUnStaked, nonce, common.NewList)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flag is missing here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stakeNodesFromQueue (numUnstaked) is missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, forgot about the flag, added it;
stakeNodesFromQueue is called on L301

if err != nil {
return err
}

err = s.fillStakingDataForNonEligible(validatorInfos)
numUnStaked, err := s.unStakeNonEligibleNodes(validatorsInfoMap, epoch)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add "withNotEnoughFunds"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to unStakeNonEligibleNodesWithNotEnoughFunds

validatorsInfoMap map[uint32][]*state.ValidatorInfo,
header data.HeaderHandler,
) error {
err := s.processWithOldFlags(validatorsInfoMap, header.GetNonce(), header.GetEpoch())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does "new" and "old" mean? They are so relative based on the epoch flags.
This just became a hard to comprehend function

Copy link
Contributor

@iulianpascalau iulianpascalau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to my last comment

Copy link
Contributor

@iulianpascalau iulianpascalau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code separation in a different PR

@iulianpascalau iulianpascalau merged commit 8f09c2d into feat/liquid-staking Mar 9, 2022
@iulianpascalau iulianpascalau deleted the EN-11662-filter-new-nodes branch March 9, 2022 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants