1use std::fmt::{Debug, Display};
2use std::marker::PhantomData;
3
4use malachite_signing_ed25519::Ed25519;
5use malachite_types::{Height as _, NilOrVal, Round, SignedExtension, ValueId, VoteType};
6use serde::{Deserialize, Serialize};
7
8use crate::{ProposerSelector, PublicKey, VotingPower};
9
10#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Default, Hash, Serialize, Deserialize)]
12pub(super) struct ValidatorAddress<A>(A);
13
14impl<A> ValidatorAddress<A> {
15 pub fn into_inner(self) -> A {
16 self.0
17 }
18}
19
20impl<A: crate::ValidatorAddress> From<A> for ValidatorAddress<A> {
21 fn from(address: A) -> Self {
22 Self(address)
23 }
24}
25
26impl<A: crate::ValidatorAddress> malachite_types::Address for ValidatorAddress<A> {}
27
28impl<A: Display> Display for ValidatorAddress<A> {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(f, "{}", self.0)
31 }
32}
33
34impl<A: Debug> Debug for ValidatorAddress<A> {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{:?}", self.0)
37 }
38}
39
40#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Default)]
42pub(super) struct Height(u64);
43
44impl Height {
45 pub fn new(height: impl Into<u64>) -> Self {
46 Self(height.into())
47 }
48}
49
50impl Display for Height {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}", self.0)
53 }
54}
55
56impl Debug for Height {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62impl malachite_types::Height for Height {
63 const ZERO: Self = Self(0);
64 const INITIAL: Self = Self(0);
65
66 fn increment_by(&self, n: u64) -> Self {
67 Self(self.0 + n)
68 }
69
70 fn decrement_by(&self, n: u64) -> Option<Self> {
71 self.0.checked_sub(n).map(Self)
72 }
73
74 fn as_u64(&self) -> u64 {
75 self.0
76 }
77
78 fn increment(&self) -> Self {
79 Self(self.0 + 1)
80 }
81
82 fn decrement(&self) -> Option<Self> {
83 self.0.checked_sub(1).map(Self)
84 }
85}
86
87impl From<Round> for crate::Round {
88 fn from(value: Round) -> Self {
89 match value {
90 Round::Nil => crate::Round::nil(),
91 Round::Some(round) => crate::Round::new(round),
92 }
93 }
94}
95
96impl From<crate::Round> for Round {
97 fn from(value: crate::Round) -> Self {
98 match value.0 {
99 Some(round) => Round::Some(round),
100 None => Round::Nil,
101 }
102 }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
107pub(super) struct Proposal<V, A> {
108 pub height: Height,
109 pub round: Round,
110 pub value: ConsensusValue<V>,
111 pub pol_round: Round,
112 pub proposer: ValidatorAddress<A>,
113}
114
115impl<V, A> From<crate::Proposal<V, A>> for Proposal<V, A> {
116 fn from(proposal: crate::Proposal<V, A>) -> Self {
117 Self {
118 height: Height::new(proposal.height),
119 round: proposal.round.into(),
120 value: ConsensusValue(proposal.value),
121 pol_round: proposal.pol_round.into(),
122 proposer: ValidatorAddress(proposal.proposer),
123 }
124 }
125}
126
127impl<V, A> From<Proposal<V, A>> for crate::Proposal<V, A> {
128 fn from(proposal: Proposal<V, A>) -> Self {
129 Self {
130 height: proposal.height.as_u64(),
131 round: proposal.round.into(),
132 value: proposal.value.into_inner(),
133 pol_round: proposal.pol_round.into(),
134 proposer: proposal.proposer.into_inner(),
135 }
136 }
137}
138
139impl<
140 A: crate::ValidatorAddress + 'static,
141 V: crate::ValuePayload + 'static,
142 P: ProposerSelector<A> + Send + Sync + 'static,
143 > malachite_types::Proposal<MalachiteContext<V, A, P>> for Proposal<V, A>
144{
145 fn height(&self) -> Height {
146 self.height
147 }
148
149 fn round(&self) -> malachite_types::Round {
150 self.round
151 }
152
153 fn value(&self) -> &ConsensusValue<V> {
154 &self.value
155 }
156
157 fn take_value(self) -> ConsensusValue<V> {
158 self.value
159 }
160
161 fn pol_round(&self) -> malachite_types::Round {
162 self.pol_round
163 }
164
165 fn validator_address(&self) -> &ValidatorAddress<A> {
166 &self.proposer
167 }
168}
169
170#[derive(Debug, Clone, Eq, PartialEq)]
173pub(super) struct ProposalPart;
174
175impl<
176 V: crate::ValuePayload + 'static,
177 A: crate::ValidatorAddress + 'static,
178 P: ProposerSelector<A> + Send + Sync + 'static,
179 > malachite_types::ProposalPart<MalachiteContext<V, A, P>> for ProposalPart
180{
181 fn is_first(&self) -> bool {
182 false
183 }
184
185 fn is_last(&self) -> bool {
186 false
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
192pub(super) struct Validator<A> {
193 pub address: ValidatorAddress<A>,
194 pub public_key: PublicKey,
195 pub voting_power: VotingPower,
196}
197
198impl<A> From<crate::Validator<A>> for Validator<A> {
199 fn from(validator: crate::Validator<A>) -> Self {
200 Self {
201 address: ValidatorAddress(validator.address),
202 public_key: validator.public_key,
203 voting_power: validator.voting_power,
204 }
205 }
206}
207
208impl<
209 V: crate::ValuePayload + 'static,
210 A: crate::ValidatorAddress + 'static,
211 P: ProposerSelector<A> + Send + Sync + 'static,
212 > malachite_types::Validator<MalachiteContext<V, A, P>> for Validator<A>
213{
214 fn address(&self) -> &ValidatorAddress<A> {
215 &self.address
216 }
217
218 fn public_key(&self) -> &PublicKey {
219 &self.public_key
220 }
221
222 fn voting_power(&self) -> malachite_types::VotingPower {
223 self.voting_power
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq)]
229pub(super) struct ValidatorSet<V, A> {
230 pub validators: Vec<Validator<A>>,
231 _phantom_v: PhantomData<V>,
232}
233
234impl<V, A> From<crate::ValidatorSet<A>> for ValidatorSet<V, A> {
235 fn from(validator_set: crate::ValidatorSet<A>) -> Self {
236 Self {
237 validators: validator_set
238 .validators
239 .into_iter()
240 .map(Into::into)
241 .collect(),
242 _phantom_v: PhantomData,
243 }
244 }
245}
246
247impl<
248 V: crate::ValuePayload + 'static,
249 A: crate::ValidatorAddress + 'static,
250 P: ProposerSelector<A> + Send + Sync + 'static,
251 > malachite_types::ValidatorSet<MalachiteContext<V, A, P>> for ValidatorSet<V, A>
252{
253 fn count(&self) -> usize {
254 self.validators.len()
255 }
256
257 fn total_voting_power(&self) -> malachite_types::VotingPower {
258 self.validators.iter().map(|v| v.voting_power).sum()
259 }
260
261 fn get_by_address(&self, address: &ValidatorAddress<A>) -> Option<&Validator<A>> {
262 self.validators.iter().find(|v| &v.address == address)
263 }
264
265 fn get_by_index(&self, index: usize) -> Option<&Validator<A>> {
266 self.validators.get(index)
267 }
268}
269
270#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
272pub(super) struct ConsensusValue<V>(V);
273
274impl<V> ConsensusValue<V> {
275 pub fn into_inner(self) -> V {
276 self.0
277 }
278}
279
280impl<V> From<V> for ConsensusValue<V> {
281 fn from(value: V) -> Self {
282 Self(value)
283 }
284}
285
286impl<V: crate::ValuePayload + 'static> malachite_types::Value for ConsensusValue<V> {
287 type Id = V;
288
289 fn id(&self) -> Self::Id {
290 self.0.clone()
291 }
292}
293
294#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
296pub(super) struct Vote<V, A> {
297 pub r#type: VoteType,
298 pub height: Height,
299 pub round: Round,
300 pub value: NilOrVal<V>,
301 pub validator_address: ValidatorAddress<A>,
302}
303
304impl<V, A> From<crate::Vote<V, A>> for Vote<V, A> {
305 fn from(vote: crate::Vote<V, A>) -> Self {
306 Self {
307 r#type: match vote.r#type {
308 crate::VoteType::Prevote => VoteType::Prevote,
309 crate::VoteType::Precommit => VoteType::Precommit,
310 },
311 height: Height::new(vote.height),
312 round: vote.round.into(),
313 value: match vote.value {
314 Some(value) => NilOrVal::Val(value),
315 None => NilOrVal::Nil,
316 },
317 validator_address: ValidatorAddress(vote.validator_address),
318 }
319 }
320}
321
322impl<V, A> From<Vote<V, A>> for crate::Vote<V, A> {
323 fn from(vote: Vote<V, A>) -> Self {
324 Self {
325 r#type: match vote.r#type {
326 VoteType::Prevote => crate::VoteType::Prevote,
327 VoteType::Precommit => crate::VoteType::Precommit,
328 },
329 height: vote.height.as_u64(),
330 round: vote.round.into(),
331 value: match vote.value {
332 NilOrVal::Val(value) => Some(value),
333 NilOrVal::Nil => None,
334 },
335 validator_address: vote.validator_address.into_inner(),
336 }
337 }
338}
339
340impl<
341 V: crate::ValuePayload + 'static,
342 A: crate::ValidatorAddress + 'static,
343 P: ProposerSelector<A> + Send + Sync + 'static,
344 > malachite_types::Vote<MalachiteContext<V, A, P>> for Vote<V, A>
345{
346 fn height(&self) -> Height {
347 self.height
348 }
349
350 fn round(&self) -> Round {
351 self.round
352 }
353
354 fn value(&self) -> &NilOrVal<V> {
355 &self.value
356 }
357
358 fn take_value(self) -> NilOrVal<V> {
359 self.value
360 }
361
362 fn vote_type(&self) -> VoteType {
363 self.r#type
364 }
365
366 fn validator_address(&self) -> &ValidatorAddress<A> {
367 &self.validator_address
368 }
369
370 fn extension(&self) -> Option<&SignedExtension<MalachiteContext<V, A, P>>> {
371 None
372 }
373
374 fn take_extension(&mut self) -> Option<SignedExtension<MalachiteContext<V, A, P>>> {
375 None
376 }
377
378 fn extend(self, _extension: SignedExtension<MalachiteContext<V, A, P>>) -> Self {
379 self
380 }
381}
382
383pub(super) struct MalachiteContext<
385 V: Send + Sync + 'static,
386 A: crate::ValidatorAddress + Send + Sync + 'static,
387 P: ProposerSelector<A> + Send + Sync + 'static,
388> {
389 proposer_selector: P,
390 _phantom_a: PhantomData<A>,
391 _phantom_v: PhantomData<V>,
392}
393
394impl<
395 V: Send + Sync + 'static,
396 A: crate::ValidatorAddress + Send + Sync + 'static,
397 P: ProposerSelector<A> + Send + Sync + 'static,
398 > MalachiteContext<V, A, P>
399{
400 pub fn new(proposer_selector: P) -> Self {
401 Self {
402 proposer_selector,
403 _phantom_a: PhantomData,
404 _phantom_v: PhantomData,
405 }
406 }
407}
408
409impl<
410 V: Send + Sync + 'static,
411 A: crate::ValidatorAddress + Send + Sync + 'static,
412 P: ProposerSelector<A> + Send + Sync + 'static,
413 > Clone for MalachiteContext<V, A, P>
414where
415 P: Clone,
416{
417 fn clone(&self) -> Self {
418 Self {
419 proposer_selector: self.proposer_selector.clone(),
420 _phantom_a: PhantomData,
421 _phantom_v: PhantomData,
422 }
423 }
424}
425
426impl<
427 V: crate::ValuePayload + 'static,
428 A: crate::ValidatorAddress + 'static,
429 P: ProposerSelector<A> + Send + Sync + 'static,
430 > malachite_types::Context for MalachiteContext<V, A, P>
431{
432 type Address = ValidatorAddress<A>;
433 type Height = Height;
434
435 type ProposalPart = ProposalPart;
436 type Proposal = Proposal<V, A>;
437
438 type Validator = Validator<A>;
439 type ValidatorSet = ValidatorSet<V, A>;
440
441 type Value = ConsensusValue<V>;
442
443 type Vote = Vote<V, A>;
444
445 type Extension = Vec<u8>;
446
447 type SigningScheme = Ed25519;
448
449 fn select_proposer<'a>(
450 &self,
451 validator_set: &'a Self::ValidatorSet,
452 height: Self::Height,
453 round: Round,
454 ) -> &'a Self::Validator {
455 let round = round.as_u32().expect("round is not nil");
456
457 let public_validator_set = crate::ValidatorSet {
459 validators: validator_set
460 .validators
461 .iter()
462 .map(|v| crate::Validator {
463 address: v.address.clone().into_inner(),
464 public_key: v.public_key,
465 voting_power: v.voting_power,
466 })
467 .collect(),
468 };
469
470 let selected_validator =
472 self.proposer_selector
473 .select_proposer(&public_validator_set, height.as_u64(), round);
474
475 let proposer = validator_set
477 .validators
478 .iter()
479 .find(|v| v.address.clone().into_inner() == selected_validator.address)
480 .expect("selected validator not found in validator set");
481
482 tracing::debug!(
483 proposer = ?proposer,
484 height = ?height,
485 round = ?round,
486 "Selected proposer for round"
487 );
488 proposer
489 }
490
491 fn new_proposal(
492 &self,
493 height: Self::Height,
494 round: Round,
495 value: Self::Value,
496 pol_round: Round,
497 address: Self::Address,
498 ) -> Self::Proposal {
499 tracing::debug!(
500 validator = %address,
501 value = ?value,
502 height = %height,
503 round = %round,
504 pol_round = %pol_round,
505 "Creating new proposal"
506 );
507 Proposal {
508 height,
509 round,
510 value,
511 proposer: address,
512 pol_round,
513 }
514 }
515
516 fn new_prevote(
517 &self,
518 height: Self::Height,
519 round: Round,
520 value_id: NilOrVal<ValueId<Self>>,
521 address: Self::Address,
522 ) -> Self::Vote {
523 tracing::debug!(
524 validator = %address,
525 value = ?value_id,
526 height = %height,
527 round = %round,
528 "Creating new prevote"
529 );
530 Vote {
531 r#type: VoteType::Prevote,
532 height,
533 round,
534 validator_address: address,
535 value: value_id,
536 }
537 }
538
539 fn new_precommit(
540 &self,
541 height: Self::Height,
542 round: Round,
543 value_id: NilOrVal<ValueId<Self>>,
544 address: Self::Address,
545 ) -> Self::Vote {
546 tracing::debug!(
547 validator = %address,
548 value = ?value_id,
549 height = %height,
550 round = %round,
551 "Creating new precommit"
552 );
553 Vote {
554 r#type: VoteType::Precommit,
555 height,
556 round,
557 validator_address: address,
558 value: value_id,
559 }
560 }
561}