diff --git a/src/main/java/com/limechain/grandpa/GrandpaService.java b/src/main/java/com/limechain/grandpa/GrandpaService.java index 08f83d99..f1125ba1 100644 --- a/src/main/java/com/limechain/grandpa/GrandpaService.java +++ b/src/main/java/com/limechain/grandpa/GrandpaService.java @@ -2,7 +2,9 @@ import com.limechain.exception.grandpa.GhostExecutionException; import com.limechain.exception.storage.BlockStorageGenericException; -import com.limechain.grandpa.state.RoundState; +import com.limechain.grandpa.state.GrandpaRound; +import com.limechain.grandpa.state.GrandpaSetState; +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.SignedMessage; import com.limechain.network.protocol.grandpa.messages.vote.Subround; @@ -16,19 +18,21 @@ import java.math.BigInteger; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; @Log @Component public class GrandpaService { - private final RoundState roundState; + private final GrandpaSetState grandpaSetState; private final BlockState blockState; - public GrandpaService(RoundState roundState, BlockState blockState) { - this.roundState = roundState; + public GrandpaService(GrandpaSetState grandpaSetState, BlockState blockState) { + this.grandpaSetState = grandpaSetState; this.blockState = blockState; } @@ -40,16 +44,16 @@ public GrandpaService(RoundState roundState, BlockState blockState) { * * @return the best final candidate block */ - public Vote getBestFinalCandidate() { + public Vote getBestFinalCandidate(GrandpaRound grandpaRound) { - Vote prevoteCandidate = getGrandpaGhost(); + Vote prevoteCandidate = getGrandpaGhost(grandpaRound); - if (roundState.getRoundNumber().equals(BigInteger.ZERO)) { + if (grandpaRound.getRoundNumber().equals(BigInteger.ZERO)) { return prevoteCandidate; } - var threshold = roundState.getThreshold(); - Map possibleSelectedBlocks = getPossibleSelectedBlocks(threshold, Subround.PRECOMMIT); + var threshold = grandpaSetState.getThreshold(); + Map possibleSelectedBlocks = getPossibleSelectedBlocks(grandpaRound, threshold, Subround.PRECOMMIT); if (possibleSelectedBlocks.isEmpty()) { return prevoteCandidate; @@ -97,14 +101,14 @@ public Vote getBestFinalCandidate() { * * @return GRANDPA GHOST block as a vote */ - public Vote getGrandpaGhost() { - var threshold = roundState.getThreshold(); + public Vote getGrandpaGhost(GrandpaRound grandpaRound) { + var threshold = grandpaSetState.getThreshold(); - if (roundState.getRoundNumber().equals(BigInteger.ZERO)) { + if (grandpaRound.getRoundNumber().equals(BigInteger.ZERO)) { return getLastFinalizedBlockAsVote(); } - Map blocks = getPossibleSelectedBlocks(threshold, Subround.PREVOTE); + Map blocks = getPossibleSelectedBlocks(grandpaRound, threshold, Subround.PREVOTE); if (blocks.isEmpty() || threshold.equals(BigInteger.ZERO)) { throw new GhostExecutionException("GHOST not found"); @@ -122,16 +126,19 @@ public Vote getGrandpaGhost() { * * @return the best pre-voted block */ - public Vote getBestPreVoteCandidate() { - Vote currentVote = getGrandpaGhost(); - VoteMessage voteMessage = roundState.getVoteMessage(); - SignedMessage signedMessage = voteMessage.getMessage(); - - if (signedMessage != null && signedMessage.getBlockNumber().compareTo(currentVote.getBlockNumber()) > 0) { - return new Vote(signedMessage.getBlockHash(), signedMessage.getBlockNumber()); - } - - return currentVote; + public Vote getBestPreVoteCandidate(GrandpaRound grandpaRound) { + Vote previousBestFinalCandidate = grandpaRound.getPrevious().getBestFinalCandidate(); + Vote currentVote = getGrandpaGhost(grandpaRound); + + return grandpaRound.getPrimaryProposals().values().stream() + .max(Comparator.comparing(signedVote -> signedVote.getVote().getBlockNumber())) + .filter(primaryVote -> { + BigInteger primaryVoteBlockNumber = primaryVote.getVote().getBlockNumber(); + return primaryVoteBlockNumber.compareTo(currentVote.getBlockNumber()) > 0 && + primaryVoteBlockNumber.compareTo(previousBestFinalCandidate.getBlockNumber()) > 0; + }) + .map(SignedVote::getVote) + .orElse(currentVote); } /** @@ -166,12 +173,12 @@ private Vote selectBlockWithMostVotes(Map blocks) { * @param subround stage of the GRANDPA process, such as PREVOTE, PRECOMMIT or PRIMARY_PROPOSAL. * @return blocks that exceed the required vote threshold */ - private Map getPossibleSelectedBlocks(BigInteger threshold, Subround subround) { - var votes = getDirectVotes(subround); + private Map getPossibleSelectedBlocks(GrandpaRound grandpaRound, BigInteger threshold, Subround subround) { + var votes = getDirectVotes(grandpaRound, subround); var blocks = new HashMap(); for (Vote vote : votes.keySet()) { - long totalVotes = getTotalVotesForBlock(vote.getBlockHash(), subround); + long totalVotes = getTotalVotesForBlock(grandpaRound, vote.getBlockHash(), subround); if (BigInteger.valueOf(totalVotes).compareTo(threshold) >= 0) { blocks.put(vote.getBlockHash(), vote.getBlockNumber()); @@ -182,10 +189,10 @@ private Map getPossibleSelectedBlocks(BigInteger threshold, return blocks; } - List allVotes = getVotes(subround); + List allVotes = getVotes(grandpaRound, subround); for (Vote vote : votes.keySet()) { blocks = new HashMap<>( - getPossibleSelectedAncestors(allVotes, vote.getBlockHash(), blocks, subround, threshold) + getPossibleSelectedAncestors(grandpaRound, allVotes, vote.getBlockHash(), blocks, subround, threshold) ); } @@ -202,7 +209,8 @@ private Map getPossibleSelectedBlocks(BigInteger threshold, * @param threshold minimum votes required for a block to qualify. * @return map of block hash to block number for ancestors meeting the threshold condition. */ - private Map getPossibleSelectedAncestors(List votes, + private Map getPossibleSelectedAncestors(GrandpaRound grandpaRound, + List votes, Hash256 currentBlockHash, Map selected, Subround subround, @@ -226,7 +234,7 @@ private Map getPossibleSelectedAncestors(List votes, return selected; } - long totalVotes = getTotalVotesForBlock(ancestorBlockHash, subround); + long totalVotes = getTotalVotesForBlock(grandpaRound, ancestorBlockHash, subround); if (BigInteger.valueOf(totalVotes).compareTo(threshold) >= 0) { @@ -235,7 +243,7 @@ private Map getPossibleSelectedAncestors(List votes, } else { // Recursively process ancestors - selected = getPossibleSelectedAncestors(votes, ancestorBlockHash, selected, subround, threshold); + selected = getPossibleSelectedAncestors(grandpaRound, votes, ancestorBlockHash, selected, subround, threshold); } } @@ -250,16 +258,16 @@ private Map getPossibleSelectedAncestors(List votes, * @param subround stage of the GRANDPA process, such as PREVOTE, PRECOMMIT or PRIMARY_PROPOSAL. * @return total votes for a specific block */ - private long getTotalVotesForBlock(Hash256 blockHash, Subround subround) { - long votesForBlock = getObservedVotesForBlock(blockHash, subround); + private long getTotalVotesForBlock(GrandpaRound grandpaRound, Hash256 blockHash, Subround subround) { + long votesForBlock = getObservedVotesForBlock(grandpaRound, blockHash, subround); if (votesForBlock == 0L) { return 0L; } int equivocationCount = switch (subround) { - case Subround.PREVOTE -> roundState.getPvEquivocations().size(); - case Subround.PRECOMMIT -> roundState.getPcEquivocations().size(); + case Subround.PREVOTE -> grandpaRound.getPvEquivocations().size(); + case Subround.PRECOMMIT -> grandpaRound.getPcEquivocations().size(); default -> 0; }; @@ -274,8 +282,8 @@ private long getTotalVotesForBlock(Hash256 blockHash, Subround subround) { * @param subround stage of the GRANDPA process, such as PREVOTE, PRECOMMIT or PRIMARY_PROPOSAL. * @return total observed votes */ - private long getObservedVotesForBlock(Hash256 blockHash, Subround subround) { - var votes = getDirectVotes(subround); + private long getObservedVotesForBlock(GrandpaRound grandpaRound, Hash256 blockHash, Subround subround) { + var votes = getDirectVotes(grandpaRound, subround); var votesForBlock = 0L; for (Map.Entry entry : votes.entrySet()) { @@ -296,22 +304,22 @@ private long getObservedVotesForBlock(Hash256 blockHash, Subround subround) { * @param subround stage of the GRANDPA process, such as PREVOTE, PRECOMMIT or PRIMARY_PROPOSAL. * @return map of direct votes */ - private HashMap getDirectVotes(Subround subround) { + private HashMap getDirectVotes(GrandpaRound grandpaRound, Subround subround) { var voteCounts = new HashMap(); - Map votes = switch (subround) { - case Subround.PREVOTE -> roundState.getPrevotes(); - case Subround.PRECOMMIT -> roundState.getPrecommits(); - default -> new HashMap<>(); + Map votes = switch (subround) { + case Subround.PREVOTE -> grandpaRound.getPreVotes(); + case Subround.PRECOMMIT -> grandpaRound.getPreCommits(); + case Subround.PRIMARY_PROPOSAL -> grandpaRound.getPrimaryProposals(); }; - votes.values().forEach(vote -> voteCounts.merge(vote, 1L, Long::sum)); + votes.values().forEach(vote -> voteCounts.merge(vote.getVote(), 1L, Long::sum)); return voteCounts; } - private List getVotes(Subround subround) { - var votes = getDirectVotes(subround); + private List getVotes(GrandpaRound grandpaRound, Subround subround) { + var votes = getDirectVotes(grandpaRound, subround); return new ArrayList<>(votes.keySet()); } diff --git a/src/main/java/com/limechain/grandpa/state/GrandpaRound.java b/src/main/java/com/limechain/grandpa/state/GrandpaRound.java new file mode 100644 index 00000000..efa23bb5 --- /dev/null +++ b/src/main/java/com/limechain/grandpa/state/GrandpaRound.java @@ -0,0 +1,30 @@ +package com.limechain.grandpa.state; + +import com.limechain.network.protocol.grandpa.messages.catchup.res.SignedVote; +import com.limechain.network.protocol.grandpa.messages.commit.Vote; +import io.emeraldpay.polkaj.types.Hash256; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +@Getter +@Setter +public class GrandpaRound { + + private GrandpaRound previous; + private BigInteger roundNumber; + + private Vote preVotedBlock; + private Vote bestFinalCandidate; + + private Map preVotes = new ConcurrentHashMap<>(); + private Map preCommits = new ConcurrentHashMap<>(); + private Map primaryProposals = new ConcurrentHashMap<>(); + + private Map> pvEquivocations = new ConcurrentHashMap<>(); + private Map> pcEquivocations = new ConcurrentHashMap<>(); +} diff --git a/src/main/java/com/limechain/grandpa/state/RoundState.java b/src/main/java/com/limechain/grandpa/state/GrandpaSetState.java similarity index 57% rename from src/main/java/com/limechain/grandpa/state/RoundState.java rename to src/main/java/com/limechain/grandpa/state/GrandpaSetState.java index d185204b..36845132 100644 --- a/src/main/java/com/limechain/grandpa/state/RoundState.java +++ b/src/main/java/com/limechain/grandpa/state/GrandpaSetState.java @@ -2,11 +2,17 @@ import com.limechain.chain.lightsyncstate.Authority; import com.limechain.chain.lightsyncstate.LightSyncState; +import com.limechain.exception.grandpa.GrandpaGenericException; 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.SignedMessage; +import com.limechain.network.protocol.grandpa.messages.vote.Subround; +import com.limechain.network.protocol.grandpa.messages.vote.VoteMessage; +import com.limechain.rpc.server.AppBean; import com.limechain.storage.DBConstants; import com.limechain.storage.KVRepository; import com.limechain.storage.StateUtil; +import io.emeraldpay.polkaj.types.Hash256; import io.libp2p.core.crypto.PubKey; import jakarta.annotation.PostConstruct; import lombok.Getter; @@ -18,7 +24,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; + +import static com.limechain.network.protocol.grandpa.messages.vote.Subround.PRECOMMIT; +import static com.limechain.network.protocol.grandpa.messages.vote.Subround.PREVOTE; +import static com.limechain.network.protocol.grandpa.messages.vote.Subround.PRIMARY_PROPOSAL; /** * Represents the state information for the current round and authorities that are needed @@ -28,25 +37,20 @@ @Getter @Setter //TODO: remove it when initialize() method is implemented @RequiredArgsConstructor -public class RoundState { +public class GrandpaSetState { private static final BigInteger THRESHOLD_DENOMINATOR = BigInteger.valueOf(3); private final KVRepository repository; private List authorities; private BigInteger setId; - private BigInteger roundNumber; - - //TODO: This may not be the best place for those maps - private Map precommits = new ConcurrentHashMap<>(); - private Map prevotes = new ConcurrentHashMap<>(); - private Map pvEquivocations = new ConcurrentHashMap<>(); - private Map pcEquivocations = new ConcurrentHashMap<>(); + private RoundCache roundCache; @PostConstruct public void initialize() { loadPersistedState(); + roundCache = AppBean.getBean(RoundCache.class); } /** @@ -69,7 +73,7 @@ private BigInteger getAuthoritiesTotalWeight() { public BigInteger derivePrimary() { var authoritiesCount = BigInteger.valueOf(authorities.size()); - return roundNumber.remainder(authoritiesCount); + return roundCache.getLatestRoundNumber(setId).remainder(authoritiesCount); } public void saveGrandpaAuthorities() { @@ -89,27 +93,31 @@ public BigInteger fetchAuthoritiesSetId() { } public void saveLatestRound() { - repository.save(DBConstants.LATEST_ROUND, roundNumber); + repository.save(DBConstants.LATEST_ROUND, roundCache.getLatestRound(setId)); } public BigInteger fetchLatestRound() { return repository.find(DBConstants.LATEST_ROUND, BigInteger.ONE); } - public void savePrevotes() { - repository.save(StateUtil.generatePrevotesKey(DBConstants.GRANDPA_PREVOTES, roundNumber, setId), prevotes); + public void savePrevotes(BigInteger roundNumber) { + GrandpaRound round = roundCache.getRound(setId, roundNumber); + Map preVotes = round.getPreVotes(); + repository.save(StateUtil.generatePrevotesKey(DBConstants.GRANDPA_PREVOTES, roundNumber, setId), preVotes); } - public Map fetchPrevotes() { + public Map fetchPrevotes(BigInteger roundNumber) { return repository.find(StateUtil.generatePrevotesKey(DBConstants.GRANDPA_PREVOTES, roundNumber, setId), Collections.emptyMap()); } - public void savePrecommits() { - repository.save(StateUtil.generatePrecommitsKey(DBConstants.GRANDPA_PRECOMMITS, roundNumber, setId), precommits); + public void savePrecommits(BigInteger roundNumber) { + GrandpaRound round = roundCache.getRound(setId, roundNumber); + Map preCommits = round.getPreCommits(); + repository.save(StateUtil.generatePrecommitsKey(DBConstants.GRANDPA_PRECOMMITS, roundNumber, setId), preCommits); } - public Map fetchPrecommits() { + public Map fetchPrecommits(BigInteger roundNumber) { return repository.find(StateUtil.generatePrecommitsKey(DBConstants.GRANDPA_PRECOMMITS, roundNumber, setId), Collections.emptyMap()); } @@ -117,17 +125,14 @@ public Map fetchPrecommits() { private void loadPersistedState() { this.authorities = Arrays.asList(fetchGrandpaAuthorities()); this.setId = fetchAuthoritiesSetId(); - this.roundNumber = fetchLatestRound(); - this.precommits = fetchPrecommits(); - this.prevotes = fetchPrevotes(); } public void persistState() { saveGrandpaAuthorities(); saveAuthoritySetId(); saveLatestRound(); - savePrecommits(); - savePrevotes(); + savePrecommits(roundCache.getLatestRoundNumber(setId)); + savePrevotes(roundCache.getLatestRoundNumber(setId)); } public BigInteger incrementSetId() { @@ -135,12 +140,30 @@ public BigInteger incrementSetId() { return setId; } - public void resetRound() { - this.roundNumber = BigInteger.ONE; - } - public void setLightSyncState(LightSyncState initState) { this.setId = initState.getGrandpaAuthoritySet().getSetId(); this.authorities = Arrays.asList(initState.getGrandpaAuthoritySet().getCurrentAuthorities()); } + + public void handleVoteMessage(VoteMessage voteMessage) { + BigInteger voteMessageSetId = voteMessage.getSetId(); + BigInteger voteMessageRoundNumber = voteMessage.getRound(); + GrandpaRound round = roundCache.getRound(voteMessageSetId, voteMessageRoundNumber); + if (round != null) { + SignedMessage signedMessage = voteMessage.getMessage(); + SignedVote signedVote = new SignedVote(); + signedVote.setVote(new Vote(signedMessage.getBlockHash(), signedMessage.getBlockNumber())); + signedVote.setSignature(signedMessage.getSignature()); + signedVote.setAuthorityPublicKey(signedMessage.getAuthorityPublicKey()); + + Subround subround = signedMessage.getStage(); + switch (subround) { + case PREVOTE -> round.getPreVotes().put(signedMessage.getAuthorityPublicKey(), signedVote); + case PRECOMMIT -> round.getPreCommits().put(signedMessage.getAuthorityPublicKey(), signedVote); + case PRIMARY_PROPOSAL -> + round.getPrimaryProposals().put(signedMessage.getAuthorityPublicKey(), signedVote); + default -> throw new GrandpaGenericException("Unknown subround: " + subround); + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/limechain/grandpa/state/RoundCache.java b/src/main/java/com/limechain/grandpa/state/RoundCache.java new file mode 100644 index 00000000..f7b8ff9d --- /dev/null +++ b/src/main/java/com/limechain/grandpa/state/RoundCache.java @@ -0,0 +1,86 @@ +package com.limechain.grandpa.state; + +import com.limechain.exception.grandpa.GrandpaGenericException; +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +// We should add new GrandpaRound objects to this structure if +// A) We receive new vote for round which is greater with 1 than the newest round that we have in this queue +// B) When we start new Play-Grandpa + +// When we finalize a round we should delete all previous GrandpaRounds +@Component +public class RoundCache { + + private static final int CACHE_SET_CAPACITY = 4; + private final Map> roundMap = new LinkedHashMap<>( + CACHE_SET_CAPACITY, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > CACHE_SET_CAPACITY; + } + }; + + public void addRound(BigInteger setId, GrandpaRound grandpaRound) { + roundMap.putIfAbsent(setId, new ArrayList<>()); + + List rounds = roundMap.get(setId); + GrandpaRound currentRound = rounds.isEmpty() ? null : rounds.getLast(); + + if (currentRound != null) { + BigInteger expectedRoundNumber = currentRound.getRoundNumber().add(BigInteger.ONE); + if (!expectedRoundNumber.equals(grandpaRound.getRoundNumber())) { + throw new GrandpaGenericException("Next round number isn't equal to the current round number plus one"); + } + + grandpaRound.setPrevious(currentRound); + } + + rounds.add(grandpaRound); + } + + public void removeRoundOlderThan(BigInteger setId, BigInteger lastFinalizedRoundNumber) { + List rounds = roundMap.get(setId); + if (rounds == null) { + return; + } + + BigInteger roundNumberBeforeLastFinalizedRound = lastFinalizedRoundNumber.subtract(BigInteger.ONE); + rounds.stream() + .filter(r -> r.getRoundNumber().equals(roundNumberBeforeLastFinalizedRound)) + .findFirst().ifPresent(roundBeforeFinalized -> roundBeforeFinalized.setPrevious(null)); + + // Remove all GrandpaRound objects with smaller numbers than the last finalized round number + rounds.removeIf(r -> r.getRoundNumber().compareTo(lastFinalizedRoundNumber) < 0); + } + + public GrandpaRound getRound(BigInteger setId, BigInteger roundNumber) { + List rounds = roundMap.get(setId); + if (rounds == null) { + return null; + } + + return rounds.stream() + .filter(r -> r.getRoundNumber().equals(roundNumber)) + .findFirst() + .orElse(null); + } + + public GrandpaRound getLatestRound(BigInteger setId) { + List rounds = roundMap.get(setId); + if (rounds == null || rounds.isEmpty()) { + return null; + } + return rounds.getLast(); + } + + public BigInteger getLatestRoundNumber(BigInteger setId) { + GrandpaRound latestRound = getLatestRound(setId); + return latestRound != null ? latestRound.getRoundNumber() : null; + } +} diff --git a/src/main/java/com/limechain/network/protocol/grandpa/GrandpaEngine.java b/src/main/java/com/limechain/network/protocol/grandpa/GrandpaEngine.java index 8a9e57d9..9c585c43 100644 --- a/src/main/java/com/limechain/network/protocol/grandpa/GrandpaEngine.java +++ b/src/main/java/com/limechain/network/protocol/grandpa/GrandpaEngine.java @@ -1,7 +1,7 @@ package com.limechain.network.protocol.grandpa; import com.limechain.exception.scale.ScaleEncodingException; -import com.limechain.grandpa.state.RoundState; +import com.limechain.grandpa.state.GrandpaSetState; import com.limechain.network.ConnectionManager; import com.limechain.network.protocol.blockannounce.messages.BlockAnnounceHandshakeBuilder; import com.limechain.network.protocol.grandpa.messages.GrandpaMessageType; @@ -42,13 +42,13 @@ public class GrandpaEngine { protected ConnectionManager connectionManager; protected WarpSyncState warpSyncState; protected BlockAnnounceHandshakeBuilder handshakeBuilder; - protected RoundState roundState; + protected GrandpaSetState grandpaSetState; public GrandpaEngine() { connectionManager = ConnectionManager.getInstance(); warpSyncState = AppBean.getBean(WarpSyncState.class); handshakeBuilder = new BlockAnnounceHandshakeBuilder(); - roundState = AppBean.getBean(RoundState.class); + grandpaSetState = AppBean.getBean(GrandpaSetState.class); } /** @@ -144,7 +144,7 @@ private void handleVoteMessage(byte[] message, PeerId peerId) { ScaleCodecReader reader = new ScaleCodecReader(message); VoteMessage voteMessage = reader.read(VoteMessageScaleReader.getInstance()); //Maybe we need to add possible roundNumber check - roundState.updateVoteMessage(voteMessage); + grandpaSetState.handleVoteMessage(voteMessage); //todo: handle vote message (authoring node responsibility?) log.log(Level.INFO, "Received vote message from Peer " + peerId + "\n" + voteMessage); } diff --git a/src/main/java/com/limechain/sync/warpsync/WarpSyncMachine.java b/src/main/java/com/limechain/sync/warpsync/WarpSyncMachine.java index aa605038..12bdcb54 100644 --- a/src/main/java/com/limechain/sync/warpsync/WarpSyncMachine.java +++ b/src/main/java/com/limechain/sync/warpsync/WarpSyncMachine.java @@ -3,6 +3,7 @@ import com.limechain.chain.ChainService; import com.limechain.chain.lightsyncstate.Authority; import com.limechain.chain.lightsyncstate.LightSyncState; +import com.limechain.grandpa.state.GrandpaSetState; import com.limechain.grandpa.state.RoundState; import com.limechain.network.Network; import com.limechain.network.protocol.warp.dto.WarpSyncFragment; @@ -41,19 +42,19 @@ public class WarpSyncMachine { private final WarpSyncState warpState; private final Network networkService; private final SyncState syncState; - private final RoundState roundState; + private final GrandpaSetState grandpaSetState; private final List onFinishCallbacks; public WarpSyncMachine(Network network, ChainService chainService, SyncState syncState, WarpSyncState warpSyncState, - RoundState roundState) { + GrandpaSetState grandpaSetState) { this.networkService = network; this.chainService = chainService; this.syncState = syncState; this.warpState = warpSyncState; - this.roundState = roundState; + this.grandpaSetState = grandpaSetState; this.executor = Executors.newSingleThreadExecutor(); this.scheduledAuthorityChanges = new PriorityQueue<>(Comparator.comparing(Pair::getValue0)); this.chainInformation = new ChainInformation(); @@ -78,7 +79,7 @@ public void start() { if (this.syncState.getLastFinalizedBlockNumber() .compareTo(initState.getFinalizedBlockHeader().getBlockNumber()) < 0) { this.syncState.setLightSyncState(initState); - this.roundState.setLightSyncState(initState); + this.grandpaSetState.setLightSyncState(initState); } } final Hash256 initStateHash = this.syncState.getLastFinalizedBlockHash(); @@ -108,7 +109,7 @@ public void stop() { private void finishWarpSync() { this.warpState.setWarpSyncFinished(true); this.syncState.persistState(); - this.roundState.persistState(); + this.grandpaSetState.persistState(); BlockState.getInstance().initializeAfterWarpSync( syncState.getLastFinalizedBlockHash(), diff --git a/src/test/java/com/limechain/grandpa/GrandpaServiceTest.java b/src/test/java/com/limechain/grandpa/GrandpaServiceTest.java index 30f1a5fe..f18947fb 100644 --- a/src/test/java/com/limechain/grandpa/GrandpaServiceTest.java +++ b/src/test/java/com/limechain/grandpa/GrandpaServiceTest.java @@ -1,7 +1,8 @@ package com.limechain.grandpa; import com.limechain.exception.grandpa.GhostExecutionException; -import com.limechain.grandpa.state.RoundState; +import com.limechain.grandpa.state.GrandpaRound; +import com.limechain.grandpa.state.GrandpaSetState; 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.SignedMessage; @@ -42,16 +43,17 @@ class GrandpaServiceTest { private static final byte[] THREES_ARRAY = new byte[]{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; - private RoundState roundState; + private GrandpaSetState grandpaSetState; private BlockState blockState; private GrandpaService grandpaService; + private GrandpaRound grandpaRound; @BeforeEach void setUp() { - roundState = mock(RoundState.class); + grandpaSetState = mock(GrandpaSetState.class); blockState = mock(BlockState.class); - grandpaService = new GrandpaService(roundState, blockState); - + grandpaService = new GrandpaService(grandpaSetState, blockState); + grandpaRound = new GrandpaRound(); } @Test @@ -62,11 +64,11 @@ void testGetBestFinalCandidateWithoutPreCommits() { BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrecommits()).thenReturn(Map.of()); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of()); + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), firstVote, Ed25519Utils.generateKeyPair().publicKey(), secondVote )); @@ -90,15 +92,15 @@ void testGetBestFinalCandidateWithPreCommitBlockNumberBiggerThatPreVoteBlockNumb BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), firstVote, Ed25519Utils.generateKeyPair().publicKey(), secondVote )); - when(roundState.getPrecommits()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), thirdVote )); @@ -108,7 +110,7 @@ void testGetBestFinalCandidateWithPreCommitBlockNumberBiggerThatPreVoteBlockNumb when(blockState.isDescendantOf(thirdVote.getBlockHash(), thirdVote.getBlockHash())).thenReturn(true); when(blockState.isDescendantOf(thirdVote.getBlockHash(), firstVote.getBlockHash())).thenReturn(true); - Vote result = grandpaService.getBestFinalCandidate(); + Vote result = grandpaService.getBestFinalCandidate(grandpaRound); assertNotNull(result); assertEquals(thirdVote.getBlockHash(), result.getBlockHash()); @@ -123,15 +125,15 @@ void testGetBestFinalCandidateWithPreCommitBlockNumberLessThatPreVoteBlockNumber BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(6)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), firstVote, Ed25519Utils.generateKeyPair().publicKey(), secondVote )); - when(roundState.getPrecommits()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), thirdVote )); @@ -142,7 +144,7 @@ void testGetBestFinalCandidateWithPreCommitBlockNumberLessThatPreVoteBlockNumber when(blockState.isDescendantOf(thirdVote.getBlockHash(), firstVote.getBlockHash())).thenReturn(true); when(blockState.isDescendantOf(thirdVote.getBlockHash(), blockHeader.getHash())).thenReturn(true); - Vote result = grandpaService.getBestFinalCandidate(); + Vote result = grandpaService.getBestFinalCandidate(grandpaRound); assertNotNull(result); assertEquals(blockHeader.getHash(), result.getBlockHash()); @@ -152,10 +154,10 @@ void testGetBestFinalCandidateWithPreCommitBlockNumberLessThatPreVoteBlockNumber void testGetBestFinalCandidateWhereRoundNumberIsZero() { BlockHeader blockHeader = createBlockHeader(); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(0)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(0)); when(blockState.getHighestFinalizedHeader()).thenReturn(blockHeader); - var result = grandpaService.getBestFinalCandidate(); + var result = grandpaService.getBestFinalCandidate(grandpaRound); assertEquals(blockHeader.getHash(), result.getBlockHash()); assertEquals(blockHeader.getBlockNumber(), result.getBlockNumber()); } @@ -166,15 +168,15 @@ void testGetBestPreVoteCandidate_WithSignedMessage() { VoteMessage voteMessage = mock(VoteMessage.class); SignedMessage signedMessage = mock(SignedMessage.class); - when(roundState.getVoteMessage()).thenReturn(voteMessage); +// when(grandpaSetState.getVoteMessage()).thenReturn(voteMessage); BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrecommits()).thenReturn(Map.of()); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of()); + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), currentVote )); @@ -184,7 +186,7 @@ void testGetBestPreVoteCandidate_WithSignedMessage() { when(signedMessage.getBlockNumber()).thenReturn(BigInteger.valueOf(4)); when(signedMessage.getBlockHash()).thenReturn(new Hash256(TWOS_ARRAY)); - Vote result = grandpaService.getBestPreVoteCandidate(); + Vote result = grandpaService.getBestPreVoteCandidate(grandpaRound); assertNotNull(result); @@ -197,15 +199,15 @@ void testGetBestPreVoteCandidate_WithoutSignedMessage() { Vote currentVote = new Vote(new Hash256(ONES_ARRAY), BigInteger.valueOf(3)); VoteMessage voteMessage = mock(VoteMessage.class); - when(roundState.getVoteMessage()).thenReturn(voteMessage); +// when(grandpaSetState.getVoteMessage()).thenReturn(voteMessage); BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrecommits()).thenReturn(Map.of()); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of()); + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), currentVote )); @@ -225,15 +227,15 @@ void testGetBestPreVoteCandidate_WithSignedMessageAndBlockNumberLessThanCurrentV VoteMessage voteMessage = mock(VoteMessage.class); SignedMessage signedMessage = mock(SignedMessage.class); - when(roundState.getVoteMessage()).thenReturn(voteMessage); + // when(grandpaSetState.getVoteMessage()).thenReturn(voteMessage); BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrecommits()).thenReturn(Map.of()); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreCommits()).thenReturn(Map.of()); + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), currentVote )); @@ -252,9 +254,9 @@ void testGetBestPreVoteCandidate_WithSignedMessageAndBlockNumberLessThanCurrentV @Test void testGetGrandpaGHOSTWhereNoBlocksPassThreshold() { - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(10)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrevotes()).thenReturn(Map.of()); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(10)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getPreVotes()).thenReturn(Map.of()); assertThrows(GhostExecutionException.class, () -> grandpaService.getGrandpaGhost()); } @@ -262,7 +264,7 @@ void testGetGrandpaGHOSTWhereNoBlocksPassThreshold() { void testGetGrandpaGHOSTWhereRoundNumberIsZero() { BlockHeader blockHeader = createBlockHeader(); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(0)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(0)); when(blockState.getHighestFinalizedHeader()).thenReturn(blockHeader); var result = grandpaService.getGrandpaGhost(); @@ -278,10 +280,10 @@ void testGetGrandpaGHOSTWithBlockPassingThreshold() { BlockHeader blockHeader = createBlockHeader(); blockHeader.setBlockNumber(BigInteger.valueOf(1)); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(1)); + when(grandpaRound.getRoundNumber()).thenReturn(BigInteger.valueOf(1)); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), firstVote, Ed25519Utils.generateKeyPair().publicKey(), secondVote )); @@ -308,7 +310,7 @@ void testGetDirectVotesForPrevotes() throws Exception { prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); // Call the private method via reflection Method method = GrandpaService.class.getDeclaredMethod("getDirectVotes", Subround.class); @@ -333,7 +335,7 @@ void testGetDirectVotesWithMultipleVotesForSingleBlockForPrevotes() throws Excep prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); // Call the private method via reflection Method method = GrandpaService.class.getDeclaredMethod("getDirectVotes", Subround.class); @@ -354,7 +356,7 @@ void testGetVotes() throws Exception { Map prevotes = new HashMap<>(); prevotes.put(pubKey1, firstVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); // Call the private method via reflection Method method = GrandpaService.class.getDeclaredMethod("getVotes", Subround.class); @@ -378,7 +380,7 @@ void testGetVotesWithMultipleVotes() throws Exception { prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); // Call the private method via reflection Method method = GrandpaService.class.getDeclaredMethod("getVotes", Subround.class); @@ -402,7 +404,7 @@ void testGetObservedVotesForBlockWhereVotesAreNotDescendantsOfProvidedBlockHash( prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); when(blockState.isDescendantOf(any(), any())).thenReturn(false); Method method = GrandpaService.class.getDeclaredMethod( @@ -430,7 +432,7 @@ void testGetObservedVotesForBlockWhereVotesAreDescendantsOfProvidedBlockHash() t prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); when(blockState.isDescendantOf(any(), any())).thenReturn(true); Method method = GrandpaService.class.getDeclaredMethod( @@ -463,8 +465,8 @@ void testGetTotalVotesForBlockWithoutObservedVotes() throws Exception { Map pvEquivocations = new HashMap<>(); pvEquivocations.put(pubKey3, new SignedVote()); - when(roundState.getPrevotes()).thenReturn(prevotes); - when(roundState.getPvEquivocations()).thenReturn(pvEquivocations); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); + when(grandpaRound.getPvEquivocations()).thenReturn(pvEquivocations); when(blockState.isDescendantOf(any(), any())).thenReturn(false); Method method = GrandpaService.class.getDeclaredMethod( @@ -492,8 +494,8 @@ void testGetTotalVotesForBlockWithObservedVotes() throws Exception { prevotes.put(pubKey1, firstVote); prevotes.put(pubKey2, secondVote); - when(roundState.getPrevotes()).thenReturn(prevotes); - when(roundState.getPvEquivocations()).thenReturn(new HashMap<>()); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); + when(grandpaRound.getPvEquivocations()).thenReturn(new HashMap<>()); when(blockState.isDescendantOf(any(), any())).thenReturn(true); Method method = GrandpaService.class.getDeclaredMethod( @@ -526,8 +528,8 @@ void testGetTotalVotesForBlockWithObservedVotesAndEquivocations() throws Excepti Map pvEquivocations = new HashMap<>(); pvEquivocations.put(pubKey3, new SignedVote()); - when(roundState.getPrevotes()).thenReturn(prevotes); - when(roundState.getPvEquivocations()).thenReturn(pvEquivocations); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); + when(grandpaRound.getPvEquivocations()).thenReturn(pvEquivocations); when(blockState.isDescendantOf(any(), any())).thenReturn(true); Method method = GrandpaService.class.getDeclaredMethod( @@ -558,8 +560,8 @@ void testGetPossibleSelectedAncestors() throws Exception { Map prevotes = new HashMap<>(); prevotes.put(pubKey1, firstVote); - when(roundState.getPrevotes()).thenReturn(prevotes); - when(roundState.getPvEquivocations()).thenReturn(new HashMap<>()); + when(grandpaRound.getPreVotes()).thenReturn(prevotes); + when(grandpaRound.getPvEquivocations()).thenReturn(new HashMap<>()); when(blockState.isDescendantOf(any(), any())).thenReturn(true); when(blockState.lowestCommonAncestor(new Hash256(ONES_ARRAY), new Hash256(THREES_ARRAY))) @@ -599,13 +601,13 @@ void testGetPossibleSelectedBlocksThatAreOverThreshold() throws Exception { Vote firstVote = new Vote(new Hash256(ONES_ARRAY), BigInteger.valueOf(3)); Vote secondVote = new Vote(new Hash256(TWOS_ARRAY), BigInteger.valueOf(4)); - when(roundState.getPrevotes()).thenReturn(Map.of( + when(grandpaRound.getPreVotes()).thenReturn(Map.of( Ed25519Utils.generateKeyPair().publicKey(), firstVote, Ed25519Utils.generateKeyPair().publicKey(), secondVote )); when(blockState.isDescendantOf(any(), any())).thenReturn(true); - when(roundState.getThreshold()).thenReturn(BigInteger.valueOf(3)); + when(grandpaSetState.getThreshold()).thenReturn(BigInteger.valueOf(3)); Method method = GrandpaService.class.getDeclaredMethod( "getPossibleSelectedBlocks", BigInteger.class, Subround.class); diff --git a/src/test/java/com/limechain/grandpa/state/RoundStateTest.java b/src/test/java/com/limechain/grandpa/state/GrandpaSetStateTest.java similarity index 79% rename from src/test/java/com/limechain/grandpa/state/RoundStateTest.java rename to src/test/java/com/limechain/grandpa/state/GrandpaSetStateTest.java index 439a39fc..565f561f 100644 --- a/src/test/java/com/limechain/grandpa/state/RoundStateTest.java +++ b/src/test/java/com/limechain/grandpa/state/GrandpaSetStateTest.java @@ -13,10 +13,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(MockitoExtension.class) -class RoundStateTest { +class GrandpaSetStateTest { @InjectMocks - private RoundState roundState; + private GrandpaSetState grandpaSetState; @Test void testGetThreshold() { @@ -31,7 +31,7 @@ void testGetThreshold() { Authority authority9 = new Authority(Ed25519Utils.generateKeyPair().publicKey().bytes(), BigInteger.ONE); Authority authority10 = new Authority(Ed25519Utils.generateKeyPair().publicKey().bytes(), BigInteger.ONE); - roundState.setAuthorities( + grandpaSetState.setAuthorities( List.of( authority1, authority2, authority3, authority4, authority5, authority6, authority7, authority8, authority9, authority10 @@ -41,7 +41,7 @@ void testGetThreshold() { // Total weight: 10 // Faulty: (10 - 1) / 3 = 3 // Threshold: 10 - faulty = 7 - assertEquals(BigInteger.valueOf(7), roundState.getThreshold()); + assertEquals(BigInteger.valueOf(7), grandpaSetState.getThreshold()); } @Test @@ -50,20 +50,20 @@ void testDerivePrimary() { Authority authority2 = new Authority(Ed25519Utils.generateKeyPair().publicKey().bytes(), BigInteger.ONE); Authority authority3 = new Authority(Ed25519Utils.generateKeyPair().publicKey().bytes(), BigInteger.ONE); - roundState.setAuthorities(List.of( + grandpaSetState.setAuthorities(List.of( authority1, authority2, authority3 )); // 4 % voters.size = 1 - roundState.setRoundNumber(BigInteger.valueOf(4)); - assertEquals(BigInteger.ONE, roundState.derivePrimary()); + grandpaSetState.setRoundNumber(BigInteger.valueOf(4)); + assertEquals(BigInteger.ONE, grandpaSetState.derivePrimary()); // 5 % voters.size = 2 - roundState.setRoundNumber(BigInteger.valueOf(5)); - assertEquals(BigInteger.TWO, roundState.derivePrimary()); + grandpaSetState.setRoundNumber(BigInteger.valueOf(5)); + assertEquals(BigInteger.TWO, grandpaSetState.derivePrimary()); // 6 % voters.size = 0 - roundState.setRoundNumber(BigInteger.valueOf(6)); - assertEquals(BigInteger.ZERO, roundState.derivePrimary()); + grandpaSetState.setRoundNumber(BigInteger.valueOf(6)); + assertEquals(BigInteger.ZERO, grandpaSetState.derivePrimary()); } } diff --git a/src/test/java/com/limechain/network/protocol/grandpa/GrandpaEngineTest.java b/src/test/java/com/limechain/network/protocol/grandpa/GrandpaEngineTest.java index 6d4471d5..79fedd30 100644 --- a/src/test/java/com/limechain/network/protocol/grandpa/GrandpaEngineTest.java +++ b/src/test/java/com/limechain/network/protocol/grandpa/GrandpaEngineTest.java @@ -1,6 +1,6 @@ package com.limechain.network.protocol.grandpa; -import com.limechain.grandpa.state.RoundState; +import com.limechain.grandpa.state.GrandpaSetState; import com.limechain.network.ConnectionManager; import com.limechain.network.dto.PeerInfo; import com.limechain.network.protocol.blockannounce.NodeRole; @@ -49,7 +49,7 @@ class GrandpaEngineTest { @Mock private WarpSyncState warpSyncState; @Mock - private RoundState roundState; + private GrandpaSetState grandpaSetState; @Mock private BlockAnnounceHandshakeBuilder blockAnnounceHandshakeBuilder;