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

Add PreviousList to peersAccount/validatorInfo/shardValidatorInfo #4961

Merged
merged 7 commits into from Feb 10, 2023

Conversation

mariusmihaic
Copy link
Contributor

@mariusmihaic mariusmihaic commented Feb 6, 2023

Reasoning behind the pull request

  • There is no easy way to find a peersAccount/validatorInfo/shardValidatorInfo previous list, especially for a node that is starting in epoch or restarting without db.
  • There are currently two bugs in indexHashedNodesCoordinator when computing the new nodes config from current epoch.
  1. In case of a node restart without db/start in epoch, previousConfig was actually using the nodes config from epoch 0.
  2. In case of a leaving/unstaked node, which would be forced to remain, the wrongful previousConfig would be used to make nodes remain eligibile (wrongful nodes)

Proposed changes

  • Added PreviousList in peersAccount/validatorInfo/shardValidatorInfo and changed their used interfaces + regenerated proto files.
  • In order to maintain backwards compatibility, when setting a validator list, added an extra flag updatePreviousList, e.g.: SetList(list string, updatePreviousList bool), which will be called with StakingV4StartedFlag - meaning this fix will be enabled only with stakingV4
  • Removed previousConfig from indexHashedNodesCoordinator and used PreviousList to compute new nodes config

Testing procedure

  • System test scenario with unstaked eligible/waiting/auction nodes with restarts without db.

Pre-requisites

Based on the Contributing Guidelines the PR author and the reviewers must check the following requirements are met:

  • was the PR targeted to the correct branch?
  • if this is a larger feature that probably needs more than one PR, is there a feat branch created?
  • if this is a feat branch merging, do all satellite projects have a proper tag inside go.mod?

@codecov-commenter
Copy link

Codecov Report

❗ No coverage uploaded for pull request base (feat/staking-v4@e6410fc). Click here to learn what that means.
Patch has no changes to coverable lines.

❗ Current head f240a85 differs from pull request most recent head c68c30f. Consider uploading reports for the commit c68c30f to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files
@@                Coverage Diff                 @@
##             feat/staking-v4    #4961   +/-   ##
==================================================
  Coverage                   ?   70.87%           
==================================================
  Files                      ?      662           
  Lines                      ?    86501           
  Branches                   ?        0           
==================================================
  Hits                       ?    61304           
  Misses                     ?    20647           
  Partials                   ?     4550           

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@mariusmihaic mariusmihaic self-assigned this Feb 6, 2023
@mariusmihaic mariusmihaic marked this pull request as ready for review February 7, 2023 09:00
@sasurobert sasurobert self-requested a review February 7, 2023 09:10
@@ -52,4 +52,5 @@ message PeerAccountData {
uint32 TotalValidatorIgnoredSignaturesRate = 16 [(gogoproto.jsontag) = "totalValidatorIgnoredSignaturesRate"];
uint64 Nonce = 17 [(gogoproto.jsontag) = "nonce"];
uint32 UnStakedEpoch = 18 [(gogoproto.jsontag) = "unStakedEpoch"];
string PreviousList = 19 [(gogoproto.jsontag) = "previousList,omitempty"];
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not backward compatible. peerAccount is written into the validator statistics trie.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did some searching and testing and it seems it is backwards compatible.
According to this source:

maintaining backwards compatibility is crucial. Protocol buffers allow for the seamless support of changes, including the addition of new fields and the deletion of existing fields, to any protocol buffer without breaking existing services

New code will also transparently read old messages. New fields will not be present in old messages; in these cases protocol buffers provide a reasonable default value.

Also, I did a unit test which confirms this:

func TestDsa(t *testing.T) {
	str1 := &ShardValidatorInfo{
		PublicKey:    []byte("pk"),
		ShardId:      4,
		List:         "list",
		Index:        5,
		TempRating:   6,
		PreviousList: "",
	}

	str2 := &ShardValidatorInfo2{
		PublicKey:  []byte("pk"),
		ShardId:    4,
		List:       "list",
		Index:      5,
		TempRating: 6,
	}

	marshaller := &marshal.GogoProtoMarshalizer{}
	bytesStr1, err := marshaller.Marshal(str1)
	require.Nil(t, err)

	bytesStr2, err := marshaller.Marshal(str2)
	require.Nil(t, err)

	require.Equal(t, bytesStr1, bytesStr2)
}

Both versions return the same marshalled byte array:

  1. ShardValidatorInfo has PreviousList field
  2. ShardValidatorInfo2 is the old version, without added field

@@ -108,7 +108,11 @@ func (pa *peerAccount) SetTempRating(rating uint32) {
}

// SetListAndIndex will update the peer's list (eligible, waiting) and the index inside it with journal
func (pa *peerAccount) SetListAndIndex(shardID uint32, list string, index uint32) {
func (pa *peerAccount) SetListAndIndex(shardID uint32, list string, index uint32, updatePreviousList bool) {
if updatePreviousList {
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 it is better to have a peerAccountV2 - where this update is true - and leave the old code as it is.

Copy link
Contributor

Choose a reason for hiding this comment

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

And you do not need to push the boolean in the argument list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would leave the existing structure with extension field instead of creating a new struct. This is also related to my comment above.

// TODO: compare with previous nodesConfig if exists
newNodesConfig, err := ihnc.computeNodesConfigFromList(copiedPrevious, allValidatorInfo)
newNodesConfig, err := ihnc.computeNodesConfigFromList(allValidatorInfo)
Copy link
Contributor

Choose a reason for hiding this comment

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

how can this be backward compatible ? it you have no information ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is backwards compatible, since the previousConfig was never used on mainnet. It was supposed to be enabled with FixWaitingListEnableEpoch, which I've deleted in a previous PR.

Old version compatibility is maintained in addValidatorToPreviousMap :

	if !ihnc.flagStakingV4Started.IsSet() {
		eligibleMap[shardId] = append(eligibleMap[shardId], currentValidator)
		return
	}

Here, eligibleMap is not the one from previousEpoch, is actually the received list from peerMiniBlocks

@AdoAdoAdo AdoAdoAdo self-requested a review February 7, 2023 11:33
SebastianMarian
SebastianMarian previously approved these changes Feb 7, 2023
pa.PreviousList = pa.List
pa.PreviousIndexInList = pa.IndexInList
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need also a variable to hold PreviousShardID ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apparently, every time SetListAndIndex (jailed/leaving) is called, it uses the same shardID, so that doesn't change.
Also, for our use-case (leaving), I don't think there will be any future use-case where a leaving unstaked validator would be set with a different shard ID.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok

sasurobert
sasurobert previously approved these changes Feb 9, 2023
SebastianMarian
SebastianMarian previously approved these changes Feb 9, 2023
AdoAdoAdo
AdoAdoAdo previously approved these changes Feb 10, 2023
@@ -290,7 +290,7 @@ func (s *legacySystemSCProcessor) unStakeNodesWithNotEnoughFunds(
}

validatorLeaving := validatorInfo.ShallowClone()
validatorLeaving.SetList(string(common.LeavingList))
validatorLeaving.SetList(string(common.LeavingList), s.enableEpochsHandler.IsStakingV4Started())
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't need to set the index 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.

Yes, very good catch.
Updated index as well

@mariusmihaic mariusmihaic merged commit d08f285 into feat/staking-v4 Feb 10, 2023
@mariusmihaic mariusmihaic deleted the MX-13779-peers-previous-list branch February 10, 2023 14:21
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

5 participants