1mod bid;
3mod bid_addr;
4mod bid_kind;
5mod bridge;
6mod constants;
7mod delegator;
8mod delegator_bid;
9mod delegator_kind;
10mod entry_points;
11mod era_info;
12mod error;
13mod reservation;
14mod seigniorage_recipient;
15mod unbond;
16mod unbonding_purse;
17mod validator_bid;
18mod validator_credit;
19mod withdraw_purse;
20
21#[cfg(any(all(feature = "std", feature = "testing"), test))]
22use alloc::collections::btree_map::Entry;
23#[cfg(any(all(feature = "std", feature = "testing"), test))]
24use itertools::Itertools;
25
26use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
27
28pub use bid::{Bid, VESTING_SCHEDULE_LENGTH_MILLIS};
29pub use bid_addr::{BidAddr, BidAddrTag};
30pub use bid_kind::{BidKind, BidKindTag};
31pub use bridge::Bridge;
32pub use constants::*;
33pub use delegator::Delegator;
34pub use delegator_bid::DelegatorBid;
35pub use delegator_kind::DelegatorKind;
36pub use entry_points::auction_entry_points;
37pub use era_info::{EraInfo, SeigniorageAllocation};
38pub use error::Error;
39pub use reservation::Reservation;
40pub use seigniorage_recipient::{
41 SeigniorageRecipient, SeigniorageRecipientV1, SeigniorageRecipientV2,
42};
43pub use unbond::{Unbond, UnbondEra, UnbondKind};
44pub use unbonding_purse::UnbondingPurse;
45pub use validator_bid::ValidatorBid;
46pub use validator_credit::ValidatorCredit;
47pub use withdraw_purse::WithdrawPurse;
48
49#[cfg(any(feature = "testing", test))]
50pub(crate) mod gens {
51 pub use super::era_info::gens::*;
52}
53
54use crate::{account::AccountHash, EraId, PublicKey, U512};
55
56pub type DelegationRate = u8;
58
59pub type ValidatorBids = BTreeMap<PublicKey, Box<ValidatorBid>>;
61
62pub type DelegatorBids = BTreeMap<PublicKey, Vec<Box<DelegatorBid>>>;
64
65pub type Reservations = BTreeMap<PublicKey, Vec<Box<Reservation>>>;
67
68pub type ValidatorCredits = BTreeMap<PublicKey, BTreeMap<EraId, Box<ValidatorCredit>>>;
70
71pub type ValidatorWeights = BTreeMap<PublicKey, U512>;
73
74#[derive(Debug)]
75pub struct WeightsBreakout {
76 locked: ValidatorWeights,
77 unlocked_meets_min: ValidatorWeights,
78 unlocked_below_min: ValidatorWeights,
79}
80
81impl WeightsBreakout {
82 pub fn new() -> Self {
83 WeightsBreakout {
84 locked: BTreeMap::default(),
85 unlocked_meets_min: BTreeMap::default(),
86 unlocked_below_min: BTreeMap::default(),
87 }
88 }
89
90 pub fn register(
91 &mut self,
92 public_key: PublicKey,
93 weight: U512,
94 locked: bool,
95 meets_minimum: bool,
96 ) {
97 if locked {
98 self.locked.insert(public_key, weight);
99 } else if meets_minimum {
100 self.unlocked_meets_min.insert(public_key, weight);
101 } else {
102 self.unlocked_below_min.insert(public_key, weight);
103 }
104 }
105
106 pub fn locked_count(&self) -> usize {
108 self.locked.len()
109 }
110
111 pub fn unlocked_meets_min_count(&self) -> usize {
113 self.unlocked_meets_min.len()
114 }
115
116 pub fn unlocked_below_min_count(&self) -> usize {
118 self.unlocked_below_min.len()
119 }
120
121 pub fn take(self, validator_slots: usize, threshold: usize) -> ValidatorWeights {
123 let locked_count = self.locked.len();
124 if locked_count >= validator_slots {
125 return self.locked;
128 }
129 let remaining_auction_slots = validator_slots.saturating_sub(locked_count);
130 let mut unlocked_hi = self
131 .unlocked_meets_min
132 .iter()
133 .map(|(public_key, validator_bid)| (public_key.clone(), *validator_bid))
134 .collect::<Vec<(PublicKey, U512)>>();
135 unlocked_hi.sort_by(|(_, lhs), (_, rhs)| rhs.cmp(lhs));
137 let unlocked_hi_count = unlocked_hi.len();
138 let combined_count = unlocked_hi_count.saturating_add(locked_count);
139 let unlocked_low_count = self.unlocked_below_min.len();
140 if unlocked_low_count == 0
141 || unlocked_hi_count >= remaining_auction_slots
142 || combined_count >= threshold
143 {
144 return self
145 .locked
146 .into_iter()
147 .chain(unlocked_hi.into_iter().take(remaining_auction_slots))
148 .collect();
149 }
150
151 let backfill_count = threshold.saturating_sub(combined_count);
155 let mut unlocked_low = self
156 .unlocked_below_min
157 .iter()
158 .map(|(public_key, validator_bid)| (public_key.clone(), *validator_bid))
159 .collect::<Vec<(PublicKey, U512)>>();
160 unlocked_low.sort_by(|(_, lhs), (_, rhs)| rhs.cmp(lhs));
162 self.locked
163 .into_iter()
164 .chain(unlocked_hi.into_iter().take(remaining_auction_slots))
165 .chain(unlocked_low.into_iter().take(backfill_count))
166 .collect()
167 }
168}
169
170impl Default for WeightsBreakout {
171 fn default() -> Self {
172 Self::new()
173 }
174}
175
176pub type EraValidators = BTreeMap<EraId, ValidatorWeights>;
178
179pub type SeigniorageRecipientsV1 = BTreeMap<PublicKey, SeigniorageRecipientV1>;
181pub type SeigniorageRecipientsV2 = BTreeMap<PublicKey, SeigniorageRecipientV2>;
183#[allow(missing_docs)]
185pub enum SeigniorageRecipients {
186 V1(SeigniorageRecipientsV1),
187 V2(SeigniorageRecipientsV2),
188}
189
190pub type SeigniorageRecipientsSnapshotV1 = BTreeMap<EraId, SeigniorageRecipientsV1>;
192pub type SeigniorageRecipientsSnapshotV2 = BTreeMap<EraId, SeigniorageRecipientsV2>;
194#[derive(Debug)]
196#[allow(missing_docs)]
197pub enum SeigniorageRecipientsSnapshot {
198 V1(SeigniorageRecipientsSnapshotV1),
199 V2(SeigniorageRecipientsSnapshotV2),
200}
201
202impl SeigniorageRecipientsSnapshot {
203 pub fn get_seignorage_recipient(
205 &self,
206 era_id: &EraId,
207 validator_public_key: &PublicKey,
208 ) -> Option<SeigniorageRecipient> {
209 match self {
210 Self::V1(snapshot) => snapshot.get(era_id).and_then(|era| {
211 era.get(validator_public_key)
212 .map(|recipient| SeigniorageRecipient::V1(recipient.clone()))
213 }),
214 Self::V2(snapshot) => snapshot.get(era_id).and_then(|era| {
215 era.get(validator_public_key)
216 .map(|recipient| SeigniorageRecipient::V2(recipient.clone()))
217 }),
218 }
219 }
220}
221
222pub type WithdrawPurses = BTreeMap<AccountHash, Vec<WithdrawPurse>>;
224
225pub type Staking = BTreeMap<PublicKey, (ValidatorBid, BTreeMap<DelegatorKind, DelegatorBid>)>;
227
228#[cfg(any(all(feature = "std", feature = "testing"), test))]
230pub trait BidsExt {
231 fn unified_bid(&self, public_key: &PublicKey) -> Option<Bid>;
233
234 fn validator_bid(&self, public_key: &PublicKey) -> Option<ValidatorBid>;
236
237 fn bridge(
239 &self,
240 public_key: &PublicKey,
241 new_public_key: &PublicKey,
242 era_id: &EraId,
243 ) -> Option<Bridge>;
244
245 fn credit(&self, public_key: &PublicKey) -> Option<ValidatorCredit>;
247
248 fn validator_total_stake(&self, public_key: &PublicKey) -> Option<U512>;
250
251 fn delegators_by_validator_public_key(
253 &self,
254 public_key: &PublicKey,
255 ) -> Option<Vec<DelegatorBid>>;
256
257 fn delegator_by_kind(
259 &self,
260 validator_public_key: &PublicKey,
261 delegator_kind: &DelegatorKind,
262 ) -> Option<DelegatorBid>;
263
264 fn reservations_by_validator_public_key(
266 &self,
267 public_key: &PublicKey,
268 ) -> Option<Vec<Reservation>>;
269
270 fn reservation_by_kind(
272 &self,
273 validator_public_key: &PublicKey,
274 delegator_kind: &DelegatorKind,
275 ) -> Option<Reservation>;
276
277 fn unbond_by_kind(
279 &self,
280 validator_public_key: &PublicKey,
281 unbond_kind: &UnbondKind,
282 ) -> Option<Unbond>;
283
284 fn contains_validator_public_key(&self, public_key: &PublicKey) -> bool;
286
287 fn remove_by_validator_public_key(&mut self, public_key: &PublicKey);
289
290 fn delegator_map(&self) -> BTreeMap<PublicKey, Vec<DelegatorKind>>;
292
293 fn upsert(&mut self, bid_kind: BidKind);
295}
296
297#[cfg(any(all(feature = "std", feature = "testing"), test))]
298impl BidsExt for Vec<BidKind> {
299 fn unified_bid(&self, public_key: &PublicKey) -> Option<Bid> {
300 if let BidKind::Unified(bid) = self
301 .iter()
302 .find(|x| x.is_validator() && &x.validator_public_key() == public_key)?
303 {
304 Some(*bid.clone())
305 } else {
306 None
307 }
308 }
309
310 fn validator_bid(&self, public_key: &PublicKey) -> Option<ValidatorBid> {
311 if let BidKind::Validator(validator_bid) = self
312 .iter()
313 .find(|x| x.is_validator() && &x.validator_public_key() == public_key)?
314 {
315 Some(*validator_bid.clone())
316 } else {
317 None
318 }
319 }
320
321 fn bridge(
322 &self,
323 public_key: &PublicKey,
324 new_public_key: &PublicKey,
325 era_id: &EraId,
326 ) -> Option<Bridge> {
327 self.iter().find_map(|x| match x {
328 BidKind::Bridge(bridge)
329 if bridge.old_validator_public_key() == public_key
330 && bridge.new_validator_public_key() == new_public_key
331 && bridge.era_id() == era_id =>
332 {
333 Some(*bridge.clone())
334 }
335 _ => None,
336 })
337 }
338
339 fn credit(&self, public_key: &PublicKey) -> Option<ValidatorCredit> {
340 if let BidKind::Credit(credit) = self
341 .iter()
342 .find(|x| x.is_credit() && &x.validator_public_key() == public_key)?
343 {
344 Some(*credit.clone())
345 } else {
346 None
347 }
348 }
349
350 fn validator_total_stake(&self, public_key: &PublicKey) -> Option<U512> {
351 if let Some(validator_bid) = self.validator_bid(public_key) {
352 let delegator_stake = {
353 match self.delegators_by_validator_public_key(validator_bid.validator_public_key())
354 {
355 None => U512::zero(),
356 Some(delegators) => delegators.iter().map(|x| x.staked_amount()).sum(),
357 }
358 };
359 return Some(validator_bid.staked_amount() + delegator_stake);
360 }
361
362 if let BidKind::Unified(bid) = self
363 .iter()
364 .find(|x| x.is_validator() && &x.validator_public_key() == public_key)?
365 {
366 return Some(*bid.staked_amount());
367 }
368
369 None
370 }
371
372 fn delegators_by_validator_public_key(
373 &self,
374 public_key: &PublicKey,
375 ) -> Option<Vec<DelegatorBid>> {
376 let mut ret = vec![];
377 for delegator in self
378 .iter()
379 .filter(|x| x.is_delegator() && &x.validator_public_key() == public_key)
380 {
381 if let BidKind::Delegator(delegator) = delegator {
382 ret.push(*delegator.clone());
383 }
384 }
385
386 if ret.is_empty() {
387 None
388 } else {
389 Some(ret)
390 }
391 }
392
393 fn delegator_by_kind(
394 &self,
395 validator_public_key: &PublicKey,
396 delegator_kind: &DelegatorKind,
397 ) -> Option<DelegatorBid> {
398 if let BidKind::Delegator(delegator) = self.iter().find(|x| {
399 x.is_delegator()
400 && &x.validator_public_key() == validator_public_key
401 && x.delegator_kind() == Some(delegator_kind.clone())
402 })? {
403 Some(*delegator.clone())
404 } else {
405 None
406 }
407 }
408
409 fn reservations_by_validator_public_key(
410 &self,
411 validator_public_key: &PublicKey,
412 ) -> Option<Vec<Reservation>> {
413 let mut ret = vec![];
414 for reservation in self
415 .iter()
416 .filter(|x| x.is_reservation() && &x.validator_public_key() == validator_public_key)
417 {
418 if let BidKind::Reservation(reservation) = reservation {
419 ret.push(*reservation.clone());
420 }
421 }
422
423 if ret.is_empty() {
424 None
425 } else {
426 Some(ret)
427 }
428 }
429
430 fn reservation_by_kind(
431 &self,
432 validator_public_key: &PublicKey,
433 delegator_kind: &DelegatorKind,
434 ) -> Option<Reservation> {
435 if let BidKind::Reservation(reservation) = self.iter().find(|x| {
436 x.is_reservation()
437 && &x.validator_public_key() == validator_public_key
438 && x.delegator_kind() == Some(delegator_kind.clone())
439 })? {
440 Some(*reservation.clone())
441 } else {
442 None
443 }
444 }
445
446 fn unbond_by_kind(
447 &self,
448 validator_public_key: &PublicKey,
449 unbond_kind: &UnbondKind,
450 ) -> Option<Unbond> {
451 if let BidKind::Unbond(unbond) = self.iter().find(|x| {
452 x.is_unbond()
453 && &x.validator_public_key() == validator_public_key
454 && x.unbond_kind() == Some(unbond_kind.clone())
455 })? {
456 Some(*unbond.clone())
457 } else {
458 None
459 }
460 }
461
462 fn contains_validator_public_key(&self, public_key: &PublicKey) -> bool {
463 self.iter().any(|x| &x.validator_public_key() == public_key)
464 }
465
466 fn remove_by_validator_public_key(&mut self, public_key: &PublicKey) {
467 self.retain(|x| &x.validator_public_key() != public_key)
468 }
469
470 fn delegator_map(&self) -> BTreeMap<PublicKey, Vec<DelegatorKind>> {
471 let mut ret = BTreeMap::new();
472 let validators = self
473 .iter()
474 .filter(|x| x.is_validator())
475 .cloned()
476 .collect_vec();
477 for bid_kind in validators {
478 ret.insert(bid_kind.validator_public_key().clone(), vec![]);
479 }
480 let delegators = self
481 .iter()
482 .filter(|x| x.is_delegator())
483 .cloned()
484 .collect_vec();
485 for bid_kind in delegators {
486 if let BidKind::Delegator(delegator) = bid_kind {
487 match ret.entry(delegator.validator_public_key().clone()) {
488 Entry::Vacant(ve) => {
489 ve.insert(vec![delegator.delegator_kind().clone()]);
490 }
491 Entry::Occupied(mut oe) => {
492 let delegators = oe.get_mut();
493 delegators.push(delegator.delegator_kind().clone())
494 }
495 }
496 }
497 }
498 let unified = self
499 .iter()
500 .filter(|x| x.is_unified())
501 .cloned()
502 .collect_vec();
503 for bid_kind in unified {
504 if let BidKind::Unified(unified) = bid_kind {
505 let delegators = unified
506 .delegators()
507 .iter()
508 .map(|(_, y)| DelegatorKind::PublicKey(y.delegator_public_key().clone()))
509 .collect();
510 ret.insert(unified.validator_public_key().clone(), delegators);
511 }
512 }
513 ret
514 }
515
516 fn upsert(&mut self, bid_kind: BidKind) {
517 let maybe_index = match bid_kind {
518 BidKind::Unified(_) | BidKind::Validator(_) => self
519 .iter()
520 .find_position(|x| {
521 x.validator_public_key() == bid_kind.validator_public_key()
522 && x.tag() == bid_kind.tag()
523 })
524 .map(|(idx, _)| idx),
525 BidKind::Delegator(_) => self
526 .iter()
527 .find_position(|x| {
528 x.is_delegator()
529 && x.validator_public_key() == bid_kind.validator_public_key()
530 && x.delegator_kind() == bid_kind.delegator_kind()
531 })
532 .map(|(idx, _)| idx),
533 BidKind::Bridge(_) => self
534 .iter()
535 .find_position(|x| {
536 x.is_bridge()
537 && x.validator_public_key() == bid_kind.validator_public_key()
538 && x.new_validator_public_key() == bid_kind.new_validator_public_key()
539 && x.era_id() == bid_kind.era_id()
540 })
541 .map(|(idx, _)| idx),
542 BidKind::Credit(_) => self
543 .iter()
544 .find_position(|x| {
545 x.validator_public_key() == bid_kind.validator_public_key()
546 && x.tag() == bid_kind.tag()
547 && x.era_id() == bid_kind.era_id()
548 })
549 .map(|(idx, _)| idx),
550 BidKind::Reservation(_) => self
551 .iter()
552 .find_position(|x| {
553 x.is_reservation()
554 && x.validator_public_key() == bid_kind.validator_public_key()
555 && x.delegator_kind() == bid_kind.delegator_kind()
556 })
557 .map(|(idx, _)| idx),
558 BidKind::Unbond(_) => self
559 .iter()
560 .find_position(|x| {
561 x.is_unbond()
562 && x.validator_public_key() == bid_kind.validator_public_key()
563 && x.unbond_kind() == bid_kind.unbond_kind()
564 })
565 .map(|(idx, _)| idx),
566 };
567
568 match maybe_index {
569 Some(index) => {
570 self.insert(index, bid_kind);
571 }
572 None => {
573 self.push(bid_kind);
574 }
575 }
576 }
577}
578
579#[cfg(test)]
580mod prop_test_delegator {
581 use proptest::prelude::*;
582
583 use crate::{bytesrepr, gens};
584
585 proptest! {
586 #[test]
587 fn test_value_bid(bid in gens::delegator_arb()) {
588 bytesrepr::test_serialization_roundtrip(&bid);
589 }
590 }
591}
592
593#[cfg(test)]
594mod prop_test_reservation {
595 use proptest::prelude::*;
596
597 use crate::{bytesrepr, gens};
598
599 proptest! {
600 #[test]
601 fn test_value_bid(bid in gens::reservation_arb()) {
602 bytesrepr::test_serialization_roundtrip(&bid);
603 }
604 }
605}