use of com.radixdlt.consensus.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class PendingVotesTest method when_submitting_a_duplicate_vote__then_can_be_replaced_if_has_timeout.
@Test
public void when_submitting_a_duplicate_vote__then_can_be_replaced_if_has_timeout() {
final var vertexId1 = HashUtils.random256();
final var vertexId2 = HashUtils.random256();
final var vote1 = makeSignedVoteFor(mock(BFTNode.class), View.genesis(), vertexId1);
when(vote1.getTimeoutSignature()).thenReturn(Optional.empty());
when(vote1.isTimeout()).thenReturn(false);
final var vote2 = makeSignedVoteFor(mock(BFTNode.class), View.genesis(), vertexId2);
when(vote2.getTimeoutSignature()).thenReturn(Optional.of(mock(ECDSASignature.class)));
when(vote2.isTimeout()).thenReturn(true);
BFTValidatorSet validatorSet = BFTValidatorSet.from(Arrays.asList(BFTValidator.from(vote1.getAuthor(), UInt256.ONE), BFTValidator.from(vote2.getAuthor(), UInt256.ONE)));
assertTrue(this.pendingVotes.insertVote(vote1, validatorSet) instanceof VoteProcessingResult.VoteAccepted);
// submit duplicate vote, should fail
assertEquals(VoteProcessingResult.rejected(VoteRejectedReason.DUPLICATE_VOTE), this.pendingVotes.insertVote(vote1, validatorSet));
// submit again, but this time with a timeout
when(vote1.getTimeoutSignature()).thenReturn(Optional.of(mock(ECDSASignature.class)));
when(vote1.isTimeout()).thenReturn(true);
// should be accepted
assertEquals(VoteProcessingResult.accepted(), this.pendingVotes.insertVote(vote1, validatorSet));
// insert another timeout vote
final var result2 = this.pendingVotes.insertVote(vote2, validatorSet);
// and form a TC
assertTrue(result2 instanceof VoteProcessingResult.QuorumReached);
assertTrue(((VoteProcessingResult.QuorumReached) result2).getViewVotingResult() instanceof ViewVotingResult.FormedTC);
}
use of com.radixdlt.consensus.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())).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.consensus.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class EpochManagerTest method getExternalModule.
private Module getExternalModule() {
BFTNode self = BFTNode.create(ecKeyPair.getPublicKey());
return new AbstractModule() {
@Override
protected void configure() {
bind(HashSigner.class).toInstance(ecKeyPair::sign);
bind(BFTNode.class).annotatedWith(Self.class).toInstance(self);
bind(new TypeLiteral<EventDispatcher<LocalTimeoutOccurrence>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<BFTInsertUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<BFTRebuildUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<BFTHighQCUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<BFTCommittedUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<EpochLocalTimeoutOccurrence>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<EpochView>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<LocalSyncRequest>>() {
}).toInstance(syncLedgerRequestSender);
bind(new TypeLiteral<EventDispatcher<ViewQuorumReached>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<EpochViewUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<ViewUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<NoVote>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<EventDispatcher<LedgerUpdate>>() {
}).toInstance(rmock(EventDispatcher.class));
bind(new TypeLiteral<ScheduledEventDispatcher<GetVerticesRequest>>() {
}).toInstance(timeoutScheduler);
bind(new TypeLiteral<ScheduledEventDispatcher<ScheduledLocalTimeout>>() {
}).toInstance(rmock(ScheduledEventDispatcher.class));
bind(new TypeLiteral<ScheduledEventDispatcher<Epoched<ScheduledLocalTimeout>>>() {
}).toInstance(rmock(ScheduledEventDispatcher.class));
bind(new TypeLiteral<ScheduledEventDispatcher<VertexRequestTimeout>>() {
}).toInstance(rmock(ScheduledEventDispatcher.class));
bind(new TypeLiteral<RemoteEventDispatcher<Proposal>>() {
}).toInstance(proposalDispatcher);
bind(new TypeLiteral<RemoteEventDispatcher<Vote>>() {
}).toInstance(voteDispatcher);
bind(new TypeLiteral<RemoteEventDispatcher<GetVerticesRequest>>() {
}).toInstance(rmock(RemoteEventDispatcher.class));
bind(new TypeLiteral<RemoteEventDispatcher<GetVerticesResponse>>() {
}).toInstance(rmock(RemoteEventDispatcher.class));
bind(new TypeLiteral<RemoteEventDispatcher<GetVerticesErrorResponse>>() {
}).toInstance(rmock(RemoteEventDispatcher.class));
bind(new TypeLiteral<RemoteEventDispatcher<LedgerStatusUpdate>>() {
}).toInstance(rmock(RemoteEventDispatcher.class));
bind(PersistentSafetyStateStore.class).toInstance(mock(PersistentSafetyStateStore.class));
bind(NextTxnsGenerator.class).toInstance(nextTxnsGenerator);
bind(SystemCounters.class).toInstance(new SystemCountersImpl());
bind(Mempool.class).toInstance(mempool);
bind(StateComputer.class).toInstance(stateComputer);
bind(PersistentVertexStore.class).toInstance(mock(PersistentVertexStore.class));
bind(RateLimiter.class).annotatedWith(GetVerticesRequestRateLimit.class).toInstance(RateLimiter.create(Double.MAX_VALUE));
bindConstant().annotatedWith(BFTSyncPatienceMillis.class).to(50);
bindConstant().annotatedWith(PacemakerTimeout.class).to(10L);
bindConstant().annotatedWith(PacemakerRate.class).to(2.0);
bindConstant().annotatedWith(PacemakerMaxExponent.class).to(0);
bind(TimeSupplier.class).toInstance(System::currentTimeMillis);
bind(new TypeLiteral<Consumer<EpochViewUpdate>>() {
}).toInstance(rmock(Consumer.class));
}
@Provides
private ViewUpdate view(BFTConfiguration bftConfiguration) {
HighQC highQC = bftConfiguration.getVertexStoreState().getHighQC();
View view = highQC.highestQC().getView().next();
return ViewUpdate.create(view, highQC, self, self);
}
@Provides
BFTValidatorSet validatorSet() {
return BFTValidatorSet.from(Stream.of(BFTValidator.from(self, UInt256.ONE)));
}
@Provides
@LastProof
LedgerProof verifiedLedgerHeaderAndProof(BFTValidatorSet validatorSet) {
var accumulatorState = new AccumulatorState(0, HashUtils.zero256());
return LedgerProof.genesis(accumulatorState, validatorSet, 0);
}
@Provides
@LastEpochProof
LedgerProof lastEpochProof(BFTValidatorSet validatorSet) {
var accumulatorState = new AccumulatorState(0, HashUtils.zero256());
return LedgerProof.genesis(accumulatorState, validatorSet, 0);
}
@Provides
BFTConfiguration bftConfiguration(@Self BFTNode self, Hasher hasher, BFTValidatorSet validatorSet) {
var accumulatorState = new AccumulatorState(0, HashUtils.zero256());
var unverifiedVertex = UnverifiedVertex.createGenesis(LedgerHeader.genesis(accumulatorState, validatorSet, 0));
var verifiedVertex = new VerifiedVertex(unverifiedVertex, hasher.hash(unverifiedVertex));
var qc = QuorumCertificate.ofGenesis(verifiedVertex, LedgerHeader.genesis(accumulatorState, validatorSet, 0));
var proposerElection = new WeightedRotatingLeaders(validatorSet);
return new BFTConfiguration(proposerElection, validatorSet, VerifiedVertexStoreState.create(HighQC.from(qc), verifiedVertex, Optional.empty(), hasher));
}
};
}
use of com.radixdlt.consensus.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class WeightedRotatingLeadersTest method setUp.
private void setUp(int validatorSetSize, int sizeOfCache) {
this.validatorsInOrder = Stream.generate(() -> ECKeyPair.generateNew().getPublicKey()).limit(validatorSetSize).map(BFTNode::create).map(node -> BFTValidator.from(node, UInt256.ONE)).sorted(Comparator.comparing(v -> v.getNode().getKey(), KeyComparator.instance().reversed())).collect(ImmutableList.toImmutableList());
BFTValidatorSet validatorSet = BFTValidatorSet.from(validatorsInOrder);
this.weightedRotatingLeaders = new WeightedRotatingLeaders(validatorSet, sizeOfCache);
this.weightedRotatingLeaders2 = new WeightedRotatingLeaders(validatorSet, sizeOfCache);
}
use of com.radixdlt.consensus.bft.BFTValidatorSet in project radixdlt by radixdlt.
the class WeightedRotatingLeadersTest method when_validators_distributed_by_fibonacci__then_leaders_also_distributed_in_fibonacci.
@Test
public void when_validators_distributed_by_fibonacci__then_leaders_also_distributed_in_fibonacci() {
// fibonacci sequence can quickly explode so keep sizes small
final int validatorSetSize = 8;
final int sizeOfCache = 4;
final Supplier<IntStream> fibonacci = () -> Stream.iterate(new int[] { 1, 1 }, t -> new int[] { t[1], t[0] + t[1] }).mapToInt(t -> t[0]).limit(validatorSetSize);
final int sumOfPower = fibonacci.get().sum();
this.validatorsInOrder = fibonacci.get().mapToObj(p -> BFTValidator.from(BFTNode.random(), UInt256.from(p))).collect(ImmutableList.toImmutableList());
BFTValidatorSet validatorSet = BFTValidatorSet.from(validatorsInOrder);
this.weightedRotatingLeaders = new WeightedRotatingLeaders(validatorSet, sizeOfCache);
Map<BFTNode, UInt256> proposerCounts = Stream.iterate(View.of(0), View::next).limit(sumOfPower).map(this.weightedRotatingLeaders::getProposer).collect(groupingBy(p -> p, collectingAndThen(counting(), UInt256::from)));
Map<BFTNode, UInt256> expected = validatorsInOrder.stream().collect(toMap(BFTValidator::getNode, BFTValidator::getPower));
assertThat(proposerCounts).isEqualTo(expected);
}
Aggregations