8000 Remove vote when checkVote() fails in HandleGovernanceVote by ian0371 · Pull Request #1367 · klaytn/klaytn · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Aug 19, 2024. It is now read-only.

Remove vote when checkVote() fails in HandleGovernanceVote #1367

Merged
merged 11 commits into from
May 23, 2022

Conversation

ian0371
Copy link
Contributor
@ian0371 ian0371 commented May 11, 2022

Proposed changes

  • Adding an existing validator via governance.vote("governance.addvalidator", existing_val_addr) has a bug. Refer to the log below.
  • This is caused by https://github.com/klaytn/klaytn/blob/dev/governance/handler.go#L365 where checkVote() checks if the address to be added already exists in the validator set, in which case it returns WITHOUT REMOVING THE VOTE.
  • This fix removes the vote when checkVote() fails. (remove in this context means setting Casted to true)

Bug log

  • Initial setting
    For an initial council, we remove one validator so that we can add it back.
> klay.getCouncil()
["0x19c032589b76ac395d3a713088e67f9ce9edf1c6", "0x353a5fd7cd9b8d0fe3e7c65d6c3d229cd0f14533", "0xd4ca4f3f2d80fb5b2f569df45d4c28a98f48a289", "0xe0c91bc72396b6c1e937ef717bf59a90c558f285"]
> addr = klay.getCouncil()[0]
"0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
> governance.vote("governance.removevalidator", addr)
"Your vote is prepared. It will be put into the block header or applied when your node generates a block as a proposer."
> governance.myVotes
[{
    BlockNum: 6,
    Casted: true,
    Key: "governance.removevalidator",
    Value: "0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
}]
  • add validator (1)
> governance.vote("governance.addvalidator", addr)
"Your vote is prepared. It will be put into the block header or applied when your node generates a block as a proposer."
> governance.myVotes
[{
    BlockNum: 6,
    Casted: true,
    Key: "governance.removevalidator",
    Value: "0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
}, {
    BlockNum: 16,
    Casted: true,
    Key: "governance.addvalidator",
    Value: "0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
}]
  • add validator (2) with an existing address
> governance.vote("governance.addvalidator", addr)
"Your vote is prepared. It will be put into the block header or applied when your node generates a block as a proposer."
> governance.myVotes
[{
    BlockNum: 0,
    Casted: false,
    Key: "governance.addvalidator",
    Value: "0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
}, {
    BlockNum: 6,
    Casted: true,
    Key: "governance.removevalidator",
    Value: "0x19c032589b76ac395d3a713088e67f9ce9edf1c6"
}]

We can see that the second vote is not cast and it keeps appearing in every block the voter becomes the proposer.

> klay.getBlock(16).voteData
"0xf84294353a5fd7cd9b8d0fe3e7c65d6c3d229cd0f1453397676f7665726e616e63652e61646476616c696461746f729419c032589b76ac395d3a713088e67f9ce9edf1c6"
> klay.getBlock(22).voteData
"0xf84294353a5fd7cd9b8d0fe3e7c65d6c3d229cd0f1453397676f7665726e616e63652e61646476616c696461746f729419c032589b76ac395d3a713088e67f9ce9edf1c6"
> klay.getBlock(25).voteData
"0xf84294353a5fd7cd9b8d0fe3e7c65d6c3d229cd0f1453397676f7665726e616e63652e61646476616c696461746f729419c032589b76ac395d3a713088e67f9ce9edf1c6"
> klay.getBlock(28).voteData
"0xf84294353a5fd7cd9b8d0fe3e7c65d6c3d229cd0f1453397676f7665726e616e63652e61646476616c696461746f729419c032589b76ac395d3a713088e67f9ce9edf1c6"

Types of changes

Please put an x in the boxes related to your change.

  • Bugfix
  • New feature or enhancement
  • Others

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • I have read the CONTRIBUTING GUIDELINES doc
  • I have signed the CLA
  • Lint and unit tests pass locally with my changes ($ make test)
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • Any dependent changes have been merged and published in downstream modules

Related issues

  • Please leave the issue numbers or links related to this PR here.

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

@blukat29
Copy link
Contributor

@ian0371 Can you add a scenario test case in TestSnapshot_Validators_AddRemove? (https://github.com/klaytn/klaytn/blob/dev/consensus/istanbul/backend/engine_test.go#L995)
For instance, addval -> addval -> removeval -> removeval case.

I see that unit test for HandleGovernanceVote checks crucial conditions. But having an intuitive scenario as a test would be more comprehensible.

@hyunsooda
Copy link
Contributor

Let me ask a simple question. Is it invalid removing duplicated vote immediately from Vote()? Why did you delegate it to HandleGovernanceVote()?

@hyunsooda
Copy link
Contributor

Each independent test case seems separated by comment. It looks better to make an arbitrary scope case by case or split them into functions. You may consider this later.

@ian0371
Copy link
Contributor Author
ian0371 commented May 12, 2022

@hyunsooda

Let me ask a simple question. Is it invalid removing duplicated vote immediately from Vote()? Why did you delegate it to HandleGovernanceVote()?

Good question. Validator set can be fetched from istanbul.snapshot, which is inaccessible from governance package (istanbul/backend package imports governance, so the reverse cannot be done. HandleGovernanceVote() receives valset as a parameter for similar reasons).

Each independent test case seems separated by comment. It looks better to make an arbitrary scope case by case or split them into functions. You may consider this later.

I agree that the current readability is not so great. I'll take this into account later :)

@hyunsooda
Copy link
Contributor
hyunsooda commented May 13, 2022

@ian0371, Okay. then, does not have a side-effect of this post-processing?

@ian0371
Copy link
Contributor Author
ian0371 commented May 13, 2022

does not have a side-effect of this post-processing?

No, it does not have a side effect. The removing vote is rarely executed in the real world (i.e., when adding an existing validator).

@ian0371 ian0371 requested a review from blukat29 May 13, 2022 05:35
blukat29
blukat29 previously approved these changes May 13, 2022
@hyunsooda
Copy link
Contributor

Okay.. thank you.

yoomee1313
yoomee1313 previously approved these changes May 13, 2022
Comment on lines -1118 to +1164
nodeKeys = append(nodeKeys, allNodeKeys[i])
addrs = append(addrs, allAddrs[i])
includeNode(allAddrs[i], allNodeKeys[i])
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are these lines changed?

Copy link
Contributor Author
@ian0371 ian0371 May 16, 2022

Choose a reason for hiding this comment

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

@ehnuje Without them, the same node ends up twice in nodeKeys/addrs, resulting in "invalid committed seals".

Copy link
Contributor
@ehnuje ehnuje May 18, 2022

Choose a reason for hiding this comment

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

@ian0371 What I meant to say was that changing the test code because of the core code change looks strange. Do we need to sync the test code logic and the core code logic manually for this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ehnuje Changing these lines is inevitable because the existing code cannot handle the new test cases. You can consider it "fixing a bug".
I could add a new test function to verify them, but instead, I decided to reuse the existing function because most parts (i.e., except for these lines) will be reused. You might not want to go down that road.

@ian0371 ian0371 dismissed stale reviews from yoomee1313 and blukat29 via f1cb3bb May 16, 2022 01:39
@ian0371 ian0371 force-pushed the fix-addvalidator branch from f1cb3bb to 80d2ccd Compare May 16, 2022 06:12
@ian0371
Copy link
Contributor Author
ian0371 commented May 16, 2022

Rebased to the latest dev

@ian0371 ian0371 requested review from blukat29, yoomee1313 and ehnuje May 16, 2022 06:53
Copy link
Contributor
@ehnuje ehnuje left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

Copy link
Contributor
@zacscoding zacscoding left a comment

Choose a reason for hiding this comment

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

Thanks @ian0371 👍

@ian0371 ian0371 merged commit 0d5d004 into klaytn:dev May 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0