use of com.radixdlt.hotstuff.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PendingVotesTest method when_voting_again__previous_vote_is_removed.
@Test
public void when_voting_again__previous_vote_is_removed() {
BFTNode author = mock(BFTNode.class);
Vote vote = makeSignedVoteFor(author, View.genesis(), HashUtils.random256());
BFTValidatorSet validatorSet = mock(BFTValidatorSet.class);
ValidationState validationState = mock(ValidationState.class);
TimestampedECDSASignatures signatures = mock(TimestampedECDSASignatures.class);
when(validationState.signatures()).thenReturn(signatures);
when(validationState.isEmpty()).thenReturn(true);
when(validatorSet.newValidationState()).thenReturn(validationState);
when(validatorSet.containsNode(any(BFTNode.class))).thenReturn(true);
VoteData voteData = mock(VoteData.class);
BFTHeader proposed = vote.getVoteData().getProposed();
when(voteData.getProposed()).thenReturn(proposed);
// Preconditions
assertEquals(VoteProcessingResult.accepted(), this.pendingVotes.insertVote(vote, validatorSet));
assertEquals(1, this.pendingVotes.voteStateSize());
assertEquals(1, this.pendingVotes.previousVotesSize());
Vote vote2 = makeSignedVoteFor(author, View.of(1), HashUtils.random256());
// Need a different hash for this (different) vote
assertEquals(VoteProcessingResult.accepted(), this.pendingVotes.insertVote(vote2, validatorSet));
assertEquals(1, this.pendingVotes.voteStateSize());
assertEquals(1, this.pendingVotes.previousVotesSize());
}
use of com.radixdlt.hotstuff.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PendingVotesTest method when_inserting_valid_but_unaccepted_votes__then_no_qc_is_returned.
@Test
public void when_inserting_valid_but_unaccepted_votes__then_no_qc_is_returned() {
HashCode vertexId = HashUtils.random256();
Vote vote1 = makeSignedVoteFor(mock(BFTNode.class), View.genesis(), vertexId);
Vote vote2 = makeSignedVoteFor(mock(BFTNode.class), View.genesis(), vertexId);
BFTValidatorSet validatorSet = BFTValidatorSet.from(Collections.singleton(BFTValidator.from(vote1.getAuthor(), UInt256.ONE)));
VoteData voteData = mock(VoteData.class);
BFTHeader proposed = vote1.getVoteData().getProposed();
when(voteData.getProposed()).thenReturn(proposed);
assertEquals(VoteProcessingResult.rejected(VoteRejectedReason.INVALID_AUTHOR), this.pendingVotes.insertVote(vote2, validatorSet));
}
use of com.radixdlt.hotstuff.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PendingVotesTest method when_inserting_valid_and_accepted_votes__then_qc_is_formed.
@Test
public void when_inserting_valid_and_accepted_votes__then_qc_is_formed() {
BFTNode author = mock(BFTNode.class);
Vote vote = makeSignedVoteFor(author, View.genesis(), HashUtils.random256());
BFTValidatorSet validatorSet = mock(BFTValidatorSet.class);
ValidationState validationState = mock(ValidationState.class);
TimestampedECDSASignatures signatures = mock(TimestampedECDSASignatures.class);
when(validationState.addSignature(any(), anyLong(), any())).thenReturn(true);
when(validationState.complete()).thenReturn(true);
when(validationState.signatures()).thenReturn(signatures);
when(validatorSet.newValidationState()).thenReturn(validationState);
when(validatorSet.containsNode(any(BFTNode.class))).thenReturn(true);
VoteData voteData = mock(VoteData.class);
BFTHeader proposed = vote.getVoteData().getProposed();
when(voteData.getProposed()).thenReturn(proposed);
assertTrue(this.pendingVotes.insertVote(vote, validatorSet) instanceof VoteProcessingResult.QuorumReached);
}
use of com.radixdlt.hotstuff.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PendingVotesTest method when_voting_again__previous_timeoutvote_is_removed.
@Test
public void when_voting_again__previous_timeoutvote_is_removed() {
BFTNode author = mock(BFTNode.class);
Vote vote = makeSignedVoteFor(author, View.genesis(), HashUtils.random256());
when(vote.getTimeoutSignature()).thenReturn(Optional.of(mock(ECDSASignature.class)));
when(vote.isTimeout()).thenReturn(true);
BFTValidatorSet validatorSet = mock(BFTValidatorSet.class);
ValidationState validationState = mock(ValidationState.class);
TimestampedECDSASignatures signatures = mock(TimestampedECDSASignatures.class);
when(validationState.signatures()).thenReturn(signatures);
when(validationState.isEmpty()).thenReturn(true);
when(validatorSet.newValidationState()).thenReturn(validationState);
when(validatorSet.containsNode(any(BFTNode.class))).thenReturn(true);
VoteData voteData = mock(VoteData.class);
BFTHeader proposed = vote.getVoteData().getProposed();
when(voteData.getProposed()).thenReturn(proposed);
// Preconditions
assertEquals(VoteProcessingResult.accepted(), this.pendingVotes.insertVote(vote, validatorSet));
assertEquals(1, this.pendingVotes.voteStateSize());
assertEquals(1, this.pendingVotes.timeoutVoteStateSize());
assertEquals(1, this.pendingVotes.previousVotesSize());
Vote vote2 = makeSignedVoteFor(author, View.of(1), HashUtils.random256());
// Need a different hash for this (different) vote
assertEquals(VoteProcessingResult.accepted(), this.pendingVotes.insertVote(vote2, validatorSet));
assertEquals(1, this.pendingVotes.voteStateSize());
assertEquals(0, this.pendingVotes.timeoutVoteStateSize());
assertEquals(1, this.pendingVotes.previousVotesSize());
}
use of com.radixdlt.hotstuff.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PacemakerViewUpdateRaceConditionTest method test_pacemaker_view_update_race_condition.
@Test
public void test_pacemaker_view_update_race_condition() {
final DeterministicTest test = DeterministicTest.builder().numNodes(numNodes).messageSelector(MessageSelector.randomSelector(random)).messageMutator(messUpMessagesForNodeUnderTest()).pacemakerTimeout(pacemakerTimeout).overrideWithIncorrectModule(new AbstractModule() {
@ProvidesIntoSet
@ProcessOnDispatch
private EventProcessor<BFTInsertUpdate> bftInsertUpdateProcessor() {
final Map<HashCode, PreparedVertex> insertedVertices = new HashMap<>();
return bftInsertUpdate -> {
final PreparedVertex inserted = bftInsertUpdate.getInserted();
insertedVertices.putIfAbsent(inserted.getId(), inserted);
final Optional<PreparedVertex> maybeParent = Optional.ofNullable(insertedVertices.get(inserted.getParentId()));
maybeParent.ifPresent(parent -> {
if (parent.getView().equals(inserted.getView())) {
throw new IllegalStateException("Vertex can't have the same view as its parent.");
}
});
};
}
@Provides
public ProposerElection proposerElection(BFTValidatorSet validatorSet) {
final var sortedValidators = validatorSet.getValidators().stream().map(BFTValidator::getNode).sorted(Comparator.comparing(BFTNode::getKey, KeyComparator.instance().reversed())).toList();
return view -> sortedValidators.get(((int) view.number() - 1) % sortedValidators.size());
}
}).buildWithoutEpochs().runUntil(nodeUnderTestReachesView(View.of(3)));
final var counters = test.getSystemCounters(nodeUnderTestIndex);
assertThat(counters.get(SystemCounters.CounterType.BFT_VOTE_QUORUMS)).isEqualTo(// ensure that quorum was formed
2);
assertThat(counters.get(SystemCounters.CounterType.BFT_PACEMAKER_TIMEOUTS_SENT)).isEqualTo(// ensure that timeouts were processed
2);
}
Aggregations