-
Notifications
You must be signed in to change notification settings - Fork 1
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
Implemented Best PreVote Candidate algorithm #679
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,9 @@ | |
import com.limechain.exception.storage.BlockStorageGenericException; | ||
import com.limechain.grandpa.state.RoundState; | ||
import com.limechain.network.protocol.grandpa.messages.commit.Vote; | ||
import com.limechain.network.protocol.grandpa.messages.vote.SignedMessage; | ||
import com.limechain.network.protocol.grandpa.messages.vote.Subround; | ||
import com.limechain.network.protocol.grandpa.messages.vote.VoteMessage; | ||
import com.limechain.network.protocol.warp.dto.BlockHeader; | ||
import com.limechain.storage.block.BlockState; | ||
import io.emeraldpay.polkaj.types.Hash256; | ||
|
@@ -111,6 +113,27 @@ public Vote getGrandpaGhost() { | |
return selectBlockWithMostVotes(blocks); | ||
} | ||
|
||
/** | ||
* Determines what block is our pre-voted block for the current round | ||
* if we receive a vote message from the network with a | ||
* block that's greater than or equal to the current pre-voted block | ||
* and greater than the best final candidate from the last round, we choose that. | ||
* otherwise, we simply choose the head of our chain. | ||
* | ||
* @return the best pre-voted block | ||
*/ | ||
public Vote getBestPreVoteCandidate() { | ||
Vote currentVote = getGrandpaGhost(); | ||
VoteMessage voteMessage = roundState.getVoteMessage(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The getVoteMessage() would almost never return a correct value here. Check my comment under |
||
SignedMessage signedMessage = voteMessage.getMessage(); | ||
|
||
if (signedMessage != null && signedMessage.getBlockNumber().compareTo(currentVote.getBlockNumber()) > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't correctly check if we have a primary proposal vote for the current round. What's happening now is we invoke GHOST and get the current pre-vote block with most votes (B r pv in spec) and a wrong value for primary proposed block (B in spec). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To fully align with the specification, you should also add the result of Best_Final_Candidate(r - 1) in the comparison.
|
||
return new Vote(signedMessage.getBlockHash(), signedMessage.getBlockNumber()); | ||
} | ||
|
||
return currentVote; | ||
} | ||
|
||
/** | ||
* Selects the block with the most votes from the provided map of blocks. | ||
* If multiple blocks have the same number of votes, it returns the one with the highest block number. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
import com.limechain.chain.lightsyncstate.Authority; | ||
import com.limechain.network.protocol.grandpa.messages.catchup.res.SignedVote; | ||
import com.limechain.network.protocol.grandpa.messages.commit.Vote; | ||
import com.limechain.network.protocol.grandpa.messages.vote.VoteMessage; | ||
import io.libp2p.core.crypto.PubKey; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
@@ -34,6 +35,8 @@ public class RoundState { | |
private Map<PubKey, Vote> prevotes = new ConcurrentHashMap<>(); | ||
private Map<PubKey, SignedVote> pvEquivocations = new ConcurrentHashMap<>(); | ||
private Map<PubKey, SignedVote> pcEquivocations = new ConcurrentHashMap<>(); | ||
//TODO: Figure out if we need to store vote messages in round state | ||
private VoteMessage voteMessage; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This field serves the purpose of a primary proposal message from the network or from ourselves if we are the primary authority/voter. However it currently gets updated on every handled vote message in the
Regarding the TODO. The state currently holds data that belongs to different aspects of grandpa:
Imo we should separate this. We can rename this class to
|
||
|
||
/** | ||
* The threshold is determined as the total weight of authorities | ||
|
@@ -57,4 +60,8 @@ public BigInteger derivePrimary() { | |
var votersCount = BigInteger.valueOf(voters.size()); | ||
return roundNumber.remainder(votersCount); | ||
} | ||
|
||
public void updateVoteMessage(VoteMessage voteMessage) { | ||
this.voteMessage = voteMessage; | ||
} | ||
} |
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 comment explains the pseudo code of the algo from the spec, but does not reflect the code in the method.