Skip to content

Commit

Permalink
Update justification verification (#727)
Browse files Browse the repository at this point in the history
# Description

- JustificationVerifier.verify() method now has Justification as an
input parameter and also executes block ancestry validation
- JustificationVerifier.verify() method checks if there are more than 3
votes cast by single authority. The vote with the smaller block number
is considered as the valid vote, other two are counted as equivocations.
- Replace PreCommit with SignedVote in all places and delete PreCommit
object

Fixes: #655 &
#648
  • Loading branch information
Grigorov-Georgi authored Feb 3, 2025
1 parent 564abe9 commit e686679
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 161 deletions.
22 changes: 3 additions & 19 deletions src/main/java/com/limechain/grandpa/GrandpaService.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import com.limechain.network.protocol.grandpa.messages.vote.SignedMessage;
import com.limechain.network.protocol.grandpa.messages.vote.VoteMessage;
import com.limechain.network.protocol.warp.dto.BlockHeader;
import com.limechain.network.protocol.warp.dto.PreCommit;
import com.limechain.state.AbstractState;
import com.limechain.state.StateManager;
import com.limechain.storage.block.state.BlockState;
Expand Down Expand Up @@ -478,16 +477,13 @@ private List<Vote> getBlockDescendents(Vote vote, List<Vote> votes) {
* 2. During attempt-to-finalize, broadcasting a commit message for the best candidate block of the current round.
*/
private void broadcastCommitMessage(GrandpaRound grandpaRound) {
PreCommit[] precommits = transformToCompactJustificationFormat(grandpaRound.getPreCommits());
SignedVote[] preCommits = grandpaRound.getPreCommits().values().toArray(new SignedVote[0]);

CommitMessage commitMessage = new CommitMessage();
commitMessage.setSetId(stateManager.getGrandpaSetState().getSetId());
commitMessage.setRoundNumber(grandpaRound.getRoundNumber());
commitMessage.setVote(
toVote(
grandpaRound.getBestFinalCandidate()
));
commitMessage.setPreCommits(precommits);
commitMessage.setVote(toVote(grandpaRound.getBestFinalCandidate()));
commitMessage.setPreCommits(preCommits);

peerMessageCoordinator.sendCommitMessageToPeers(commitMessage);
}
Expand Down Expand Up @@ -529,18 +525,6 @@ public void broadcastPreVoteMessage(GrandpaRound grandpaRound) {
peerMessageCoordinator.sendVoteMessageToPeers(voteMessage);
}

private PreCommit[] transformToCompactJustificationFormat(Map<Hash256, SignedVote> signedVotes) {
return signedVotes.values().stream()
.map(signedVote -> {
PreCommit precommit = new PreCommit();
precommit.setTargetHash(signedVote.getVote().getBlockHash());
precommit.setTargetNumber(signedVote.getVote().getBlockNumber());
precommit.setSignature(signedVote.getSignature());
precommit.setAuthorityPublicKey(signedVote.getAuthorityPublicKey());
return precommit;
}).toArray(PreCommit[]::new);
}

private Vote toVote(BlockHeader blockHeader) {
Vote vote = new Vote();
vote.setBlockHash(blockHeader.getHash());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.limechain.network.protocol.grandpa.messages.commit;

import com.limechain.grandpa.vote.SignedVote;
import com.limechain.grandpa.vote.Vote;
import com.limechain.network.protocol.warp.dto.PreCommit;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -15,5 +15,5 @@ public class CommitMessage {
private BigInteger roundNumber;
private BigInteger setId;
private Vote vote;
private PreCommit[] preCommits;
private SignedVote[] preCommits;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.limechain.network.protocol.grandpa.messages.commit;

import com.limechain.exception.network.SignatureCountMismatchException;
import com.limechain.grandpa.vote.SignedVote;
import com.limechain.grandpa.vote.Vote;
import com.limechain.network.protocol.warp.dto.PreCommit;
import io.emeraldpay.polkaj.scale.ScaleCodecReader;
import io.emeraldpay.polkaj.scale.ScaleReader;
import io.emeraldpay.polkaj.scale.reader.ListReader;
Expand All @@ -11,7 +11,7 @@

import java.util.List;

public class CompactJustificationScaleReader implements ScaleReader<PreCommit[]> {
public class CompactJustificationScaleReader implements ScaleReader<SignedVote[]> {

private static final CompactJustificationScaleReader INSTANCE = new CompactJustificationScaleReader();

Expand All @@ -27,17 +27,15 @@ public static CompactJustificationScaleReader getInstance() {
}

@Override
public PreCommit[] read(ScaleCodecReader reader) {
public SignedVote[] read(ScaleCodecReader reader) {
List<Vote> votes = voteListReader.read(reader);

int preCommitsCount = votes.size();
PreCommit[] preCommits = new PreCommit[preCommitsCount];
SignedVote[] preCommits = new SignedVote[preCommitsCount];

for (int i = 0; i < preCommitsCount; i++) {
Vote vote = votes.get(i);
preCommits[i] = new PreCommit();
preCommits[i].setTargetHash(vote.getBlockHash());
preCommits[i].setTargetNumber(vote.getBlockNumber());
preCommits[i] = new SignedVote();
preCommits[i].setVote(votes.get(i));
}

int signaturesCount = reader.readCompactInt();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.limechain.network.protocol.grandpa.messages.commit;

import com.limechain.grandpa.vote.Vote;
import com.limechain.network.protocol.warp.dto.PreCommit;
import com.limechain.grandpa.vote.SignedVote;
import io.emeraldpay.polkaj.scale.ScaleCodecWriter;
import io.emeraldpay.polkaj.scale.ScaleWriter;

import java.io.IOException;

public class CompactJustificationScaleWriter implements ScaleWriter<PreCommit[]> {
public class CompactJustificationScaleWriter implements ScaleWriter<SignedVote[]> {

private static final CompactJustificationScaleWriter INSTANCE = new CompactJustificationScaleWriter();

Expand All @@ -22,21 +21,16 @@ public static CompactJustificationScaleWriter getInstance() {
}

@Override
public void write(ScaleCodecWriter writer, PreCommit[] preCommits) throws IOException {
public void write(ScaleCodecWriter writer, SignedVote[] preCommits) throws IOException {
writer.writeCompact(preCommits.length);

for (int i = 0; i < preCommits.length; i++) {
PreCommit preCommit = preCommits[i];
Vote vote = new Vote();
vote.setBlockHash(preCommit.getTargetHash());
vote.setBlockNumber(preCommit.getTargetNumber());
voteScaleWriter.write(writer, vote);
for (SignedVote preCommit : preCommits) {
voteScaleWriter.write(writer, preCommit.getVote());
}

writer.writeCompact(preCommits.length);

for (int i = 0; i < preCommits.length; i++) {
PreCommit preCommit = preCommits[i];
for (SignedVote preCommit : preCommits) {
writer.writeByteArray(preCommit.getSignature().getBytes());
writer.writeUint256(preCommit.getAuthorityPublicKey().getBytes());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
package com.limechain.network.protocol.warp.dto;

import com.limechain.grandpa.vote.SignedVote;
import com.limechain.network.protocol.grandpa.messages.commit.CommitMessage;
import io.emeraldpay.polkaj.types.Hash256;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.java.Log;

import java.math.BigInteger;
import java.util.Arrays;

@Setter
@Getter
@Log
public class Justification {

private BigInteger round;
private BigInteger roundNumber;
private Hash256 targetHash;
private BigInteger targetBlock;
private PreCommit[] preCommits;
private SignedVote[] signedVotes; // either preCommis or preVotes
private BlockHeader[] ancestryVotes;

public static Justification fromCommitMessage(CommitMessage commitMessage) {
Justification justification = new Justification();
justification.setRoundNumber(commitMessage.getRoundNumber());
justification.setTargetHash(commitMessage.getVote().getBlockHash());
justification.setTargetBlock(commitMessage.getVote().getBlockNumber());
justification.setSignedVotes(commitMessage.getPreCommits());
return justification;
}

@Override
public String toString() {
return "WarpSyncJustification{" +
"round=" + round +
return "Justification{" +
"roundNumber=" + roundNumber +
", targetHash=" + targetHash +
", targetBlock=" + targetBlock +
", preCommits=" + Arrays.toString(preCommits) +
", signedVotes=" + Arrays.toString(signedVotes) +
", ancestryVotes=" + Arrays.toString(ancestryVotes) +
'}';
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.limechain.network.protocol.warp.scale.reader;

import com.limechain.grandpa.vote.SignedVote;
import com.limechain.network.protocol.grandpa.messages.catchup.res.SignedVoteScaleReader;
import com.limechain.network.protocol.warp.dto.BlockHeader;
import com.limechain.network.protocol.warp.dto.Justification;
import com.limechain.network.protocol.warp.dto.PreCommit;
import io.emeraldpay.polkaj.scale.ScaleCodecReader;
import io.emeraldpay.polkaj.scale.ScaleReader;
import io.emeraldpay.polkaj.scale.reader.UInt64Reader;
Expand All @@ -22,20 +23,20 @@ public static JustificationReader getInstance() {
@Override
public Justification read(ScaleCodecReader reader) {
Justification justification = new Justification();
justification.setRound(new UInt64Reader().read(reader));
justification.setRoundNumber(new UInt64Reader().read(reader));

// Target hash and target block constitute the "GRANDPA Vote":
// https://spec.polkadot.network/sect-finality#defn-vote
justification.setTargetHash(new Hash256(reader.readUint256()));
justification.setTargetBlock(BlockNumberReader.getInstance().read(reader));

int preCommitsCount = reader.readCompactInt();
PreCommit[] preCommits = new PreCommit[preCommitsCount];
PreCommitReader preCommitReader = PreCommitReader.getInstance();
for (int i = 0; i < preCommitsCount; i++) {
preCommits[i] = preCommitReader.read(reader);
int signedVotesCount = reader.readCompactInt();
SignedVote[] signedVotes = new SignedVote[signedVotesCount];
SignedVoteScaleReader signedVoteReader = SignedVoteScaleReader.getInstance();
for (int i = 0; i < signedVotesCount; i++) {
signedVotes[i] = signedVoteReader.read(reader);
}
justification.setPreCommits(preCommits);
justification.setSignedVotes(signedVotes);

int ancestryCount = reader.readCompactInt();
BlockHeader[] ancestries = new BlockHeader[ancestryCount];
Expand Down

This file was deleted.

Loading

0 comments on commit e686679

Please sign in to comment.