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