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
Staking v4: soft auction list selection #4083
Staking v4: soft auction list selection #4083
Conversation
…implement-soft-auction # Conflicts: # epochStart/errors.go # epochStart/metachain/auctionListSelector.go # epochStart/metachain/auctionListSelector_test.go
Codecov Report
@@ Coverage Diff @@
## feat/liquid-staking #4083 +/- ##
=======================================================
+ Coverage 75.38% 75.99% +0.61%
=======================================================
Files 622 658 +36
Lines 83275 86766 +3491
=======================================================
+ Hits 62774 65936 +3162
- Misses 15776 15988 +212
- Partials 4725 4842 +117
Continue to review full report at Codecov.
|
# Conflicts: # cmd/node/config/config.toml # config/config.go # testscommon/generalConfig.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
partial review, mostly on calcSoftAuctionNodesConfig
function
sw.Start("auctionListSelector.sortAuctionList") | ||
defer func() { | ||
sw.Stop("auctionListSelector.sortAuctionList") | ||
log.Debug("time measurements", sw.GetMeasurements()...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙏
|
||
ret[string(pubKey)] = topUp | ||
// TODO: Move this in elrond-go-core | ||
func safeSub(a, b uint32) (uint32, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have this in core already I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for uint32, only for uint64 and I didn't want to cast the values
numNodesQualifyingForTopUp := int64(0) | ||
previousConfig = copyOwnersData(ownersData) | ||
|
||
for ownerPubKey, owner := range ownersData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion to extract L335-L357 in a separate function that will output the required map & numNodesQualifyingForTopUp value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted separate function
|
||
// GetTotalTopUp returns owner's total top up | ||
func (sdp *stakingDataProvider) GetTotalTopUp(owner []byte) (*big.Int, error) { | ||
ownerInfo, ok := sdp.cache[string(owner)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have some mutexes for other gets. add here as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on all gets from the cache
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now obsolete, since this func is removed in future refactor PR
return selectedFromAuction[:numAvailableSlots] | ||
} | ||
|
||
func getPubKeyLen(ownersData map[string]*ownerData) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this ? you do not need to iterate and return the lenght of data like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not iterate over all values; it stops at the first element; I need it to find the blsKeyLen so we can normalize randomness
|
||
ret[string(pubKey)] = topUp | ||
// TODO: Move this in elrond-go-core | ||
func safeSub(a, b uint32) (uint32, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have this in core already I think.
func (als *auctionListSelector) getAuctionDataAndNumOfValidators( | ||
validatorsInfoMap state.ShardValidatorsInfoMapHandler, | ||
unqualifiedOwners map[string]struct{}, | ||
) (map[string]*ownerData, uint32, uint32, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make a structure please instead of 3 returns and the error. So one struct and the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now obsolete, since this func is removed in future refactor PR
numOfValidators := uint32(0) | ||
numOfNodesInAuction := uint32(0) | ||
|
||
for _, validator := range validatorsInfoMap.GetAllValidatorsInfo() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is like double iteration - you already have the owner data in the stakingProvider component. Everything is there. You have to iterate per owner. Not per key. There are a lot of useless checks per key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, refactored all code in a separate PR: #4155
continue | ||
} | ||
|
||
err = als.addOwnerData(owner, validator, ownersData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should start from data from the stakingProvider component and add the necessary information. You need to know the keys which are in the auction list for this owner and the total topup and other global info about the owner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, refactored all code in a separate PR: #4155
numNodesQualifyingForTopUp := int64(0) | ||
previousConfig = copyOwnersData(ownersData) | ||
|
||
for ownerPubKey, owner := range ownersData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
func (als *auctionListSelector) getAuctionDataAndNumOfValidators( | ||
validatorsInfoMap state.ShardValidatorsInfoMapHandler, | ||
unqualifiedOwners map[string]struct{}, | ||
) (map[string]*ownerData, uint32, uint32, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
numNodesQualifyingForTopUp := int64(0) | ||
previousConfig = copyOwnersData(ownersData) | ||
|
||
for ownerPubKey, owner := range ownersData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+2
|
||
// GetTotalTopUp returns owner's total top up | ||
func (sdp *stakingDataProvider) GetTotalTopUp(owner []byte) (*big.Int, error) { | ||
ownerInfo, ok := sdp.cache[string(owner)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on all gets from the cache
Implemented soft(dynamic) auction selection for nodes in auction list. "Core" implementation can be found in
calcSoftAuctionNodesConfig
func, which implements the algorithm proposed here (see Pseudo code of topUp calculation)What's new
SoftAuctionConfig
config for soft auction selectionStakingDataProvider
to provideGetNumStakedNodes
&GetTotalTopUp
of an owner. Note that it is required that these information are pre-filled (which happens for all nodes inProcessSystemSC
) before callingSelectNodesFromAuctionList
SelectNodesFromAuctionList
now expects to receive all unqualified owners, of whom auction nodes will not participate at selection. These unqualified owners are the ones which do not have enough stake for their nodes, therefore one or more of their nodes will be removed at the end of the epoch.ownerData
computed and filled(active nodes, auction nodes, topUp per node, etc...) before applying the dynamic selection. After soft auction computation is done, each owner's auction nodes will be sorted (BY blsKey) and qualified ones will be marked as selected. If two/more nodes, which belong to different owners, have the same qualifiedTopUpPerNode, sorting will be done based on blsKey XOR randomness. SeeTestSystemSCProcessor_ProcessSystemSmartContractStakingV4Enabled
test which contains an example with graphic tablesBugfixes
epochStart/metachain/systemSCs.go
when preparing staking data (L134
). It was done for all nodes instead of eligible nodes only, causing rewards to be distributed to non-eligible nodes.