unc_primitives/
types.rs

1use crate::account::{AccessKey, Account};
2use crate::action::RegisterRsa2048KeysAction;
3use crate::challenge::ChallengesResult;
4use crate::errors::EpochError;
5pub use crate::hash::CryptoHash;
6use crate::receipt::Receipt;
7use crate::serialize::dec_format;
8use crate::trie_key::TrieKey;
9use borsh::{BorshDeserialize, BorshSerialize};
10use once_cell::sync::Lazy;
11use serde_with::base64::Base64;
12use serde_with::serde_as;
13use std::sync::Arc;
14use unc_crypto::PublicKey;
15/// Reexport primitive types
16pub use unc_primitives_core::types::*;
17pub use unc_vm_runner::logic::TrieNodesCount;
18
19/// Hash used by to store state root.
20pub type StateRoot = CryptoHash;
21
22/// Different types of finality.
23#[derive(
24    serde::Serialize, serde::Deserialize, Default, Clone, Debug, PartialEq, Eq, arbitrary::Arbitrary,
25)]
26pub enum Finality {
27    #[serde(rename = "optimistic")]
28    None,
29    #[serde(rename = "unc-final")]
30    DoomSlug,
31    #[serde(rename = "final")]
32    #[default]
33    Final,
34}
35
36#[derive(Debug, serde::Serialize, serde::Deserialize)]
37pub struct AccountWithPublicKey {
38    pub account_id: AccountId,
39    pub public_key: PublicKey,
40}
41
42/// Account info for validators
43#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Eq, PartialEq)]
44pub struct AccountInfo {
45    pub account_id: AccountId,
46    pub public_key: PublicKey,
47    #[serde(with = "dec_format")]
48    pub pledging: Balance,
49    #[serde(with = "dec_format")]
50    pub power: Power,
51}
52
53/// This type is used to mark keys (arrays of bytes) that are queried from store.
54///
55/// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently
56/// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`).
57#[serde_as]
58#[derive(
59    serde::Serialize,
60    serde::Deserialize,
61    Clone,
62    Debug,
63    PartialEq,
64    Eq,
65    derive_more::Deref,
66    derive_more::From,
67    derive_more::Into,
68    BorshSerialize,
69    BorshDeserialize,
70)]
71#[serde(transparent)]
72pub struct StoreKey(#[serde_as(as = "Base64")] Vec<u8>);
73
74/// This type is used to mark values returned from store (arrays of bytes).
75///
76/// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently
77/// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`).
78#[serde_as]
79#[derive(
80    serde::Serialize,
81    serde::Deserialize,
82    Clone,
83    Debug,
84    PartialEq,
85    Eq,
86    derive_more::Deref,
87    derive_more::From,
88    derive_more::Into,
89    BorshSerialize,
90    BorshDeserialize,
91)]
92#[serde(transparent)]
93pub struct StoreValue(#[serde_as(as = "Base64")] Vec<u8>);
94
95/// This type is used to mark function arguments.
96///
97/// NOTE: The main reason for this to exist (except the type-safety) is that the value is
98/// transparently serialized and deserialized as a base64-encoded string when serde is used
99/// (serde_json).
100#[serde_as]
101#[derive(
102    serde::Serialize,
103    serde::Deserialize,
104    Clone,
105    Debug,
106    PartialEq,
107    Eq,
108    derive_more::Deref,
109    derive_more::From,
110    derive_more::Into,
111    BorshSerialize,
112    BorshDeserialize,
113)]
114#[serde(transparent)]
115pub struct FunctionArgs(#[serde_as(as = "Base64")] Vec<u8>);
116
117/// A structure used to indicate the kind of state changes due to transaction/receipt processing, etc.
118#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
119pub enum StateChangeKind {
120    AccountTouched { account_id: AccountId },
121    AccessKeyTouched { account_id: AccountId },
122    DataTouched { account_id: AccountId },
123    ContractCodeTouched { account_id: AccountId },
124    RsaKeyTouched { account_id: AccountId },
125}
126
127pub type StateChangesKinds = Vec<StateChangeKind>;
128
129#[easy_ext::ext(StateChangesKindsExt)]
130impl StateChangesKinds {
131    pub fn from_changes(
132        raw_changes: &mut dyn Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
133    ) -> Result<StateChangesKinds, std::io::Error> {
134        raw_changes
135            .filter_map(|raw_change| {
136                let RawStateChangesWithTrieKey { trie_key, .. } = match raw_change {
137                    Ok(p) => p,
138                    Err(e) => return Some(Err(e)),
139                };
140                match trie_key {
141                    TrieKey::Account { account_id } => {
142                        Some(Ok(StateChangeKind::AccountTouched { account_id }))
143                    }
144                    TrieKey::ContractCode { account_id } => {
145                        Some(Ok(StateChangeKind::ContractCodeTouched { account_id }))
146                    }
147                    TrieKey::AccessKey { account_id, .. } => {
148                        Some(Ok(StateChangeKind::AccessKeyTouched { account_id }))
149                    }
150                    TrieKey::ContractData { account_id, .. } => {
151                        Some(Ok(StateChangeKind::DataTouched { account_id }))
152                    }
153                    TrieKey::Rsa2048Keys { account_id, .. } => {
154                        Some(Ok(StateChangeKind::RsaKeyTouched { account_id }))
155                    }
156                    _ => None,
157                }
158            })
159            .collect()
160    }
161}
162
163/// A structure used to index state changes due to transaction/receipt processing and other things.
164#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq)]
165pub enum StateChangeCause {
166    /// A type of update that does not get finalized. Used for verification and execution of
167    /// immutable smart contract methods. Attempt fo finalize a `TrieUpdate` containing such
168    /// change will lead to panic.
169    NotWritableToDisk,
170    /// A type of update that is used to mark the initial storage update, e.g. during genesis
171    /// or in tests setup.
172    InitialState,
173    /// Processing of a transaction.
174    TransactionProcessing { tx_hash: CryptoHash },
175    /// Before the receipt is going to be processed, inputs get drained from the state, which
176    /// causes state modification.
177    ActionReceiptProcessingStarted { receipt_hash: CryptoHash },
178    /// Computation of gas reward.
179    ActionReceiptGasReward { receipt_hash: CryptoHash },
180    /// Processing of a receipt.
181    ReceiptProcessing { receipt_hash: CryptoHash },
182    /// The given receipt was postponed. This is either a data receipt or an action receipt.
183    /// A `DataReceipt` can be postponed if the corresponding `ActionReceipt` is not received yet,
184    /// or other data dependencies are not satisfied.
185    /// An `ActionReceipt` can be postponed if not all data dependencies are received.
186    PostponedReceipt { receipt_hash: CryptoHash },
187    /// Updated delayed receipts queue in the state.
188    /// We either processed previously delayed receipts or added more receipts to the delayed queue.
189    UpdatedDelayedReceipts,
190    /// State change that happens when we update validator accounts. Not associated with with any
191    /// specific transaction or receipt.
192    ValidatorAccountsUpdate,
193    /// State change that is happens due to migration that happens in first block of an epoch
194    /// after protocol upgrade
195    Migration,
196    /// State changes for building states for re-sharding
197    Resharding,
198}
199
200/// This represents the committed changes in the Trie with a change cause.
201#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
202pub struct RawStateChange {
203    pub cause: StateChangeCause,
204    pub data: Option<Vec<u8>>,
205}
206
207/// List of committed changes with a cause for a given TrieKey
208#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
209pub struct RawStateChangesWithTrieKey {
210    pub trie_key: TrieKey,
211    pub changes: Vec<RawStateChange>,
212}
213
214/// Consolidate state change of trie_key and the final value the trie key will be changed to
215#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
216pub struct ConsolidatedStateChange {
217    pub trie_key: TrieKey,
218    pub value: Option<Vec<u8>>,
219}
220
221#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
222pub struct StateChangesForResharding {
223    pub changes: Vec<ConsolidatedStateChange>,
224    // we need to store deleted receipts here because StateChanges will only include
225    // trie keys for removed values and account information can not be inferred from
226    // trie key for delayed receipts
227    pub processed_delayed_receipts: Vec<Receipt>,
228}
229
230impl StateChangesForResharding {
231    pub fn from_raw_state_changes(
232        changes: &[RawStateChangesWithTrieKey],
233        processed_delayed_receipts: Vec<Receipt>,
234    ) -> Self {
235        let changes = changes
236            .iter()
237            .map(|RawStateChangesWithTrieKey { trie_key, changes }| {
238                let value = changes.last().expect("state_changes must not be empty").data.clone();
239                ConsolidatedStateChange { trie_key: trie_key.clone(), value }
240            })
241            .collect();
242        Self { changes, processed_delayed_receipts }
243    }
244}
245
246/// key that was updated -> list of updates with the corresponding indexing event.
247pub type RawStateChanges = std::collections::BTreeMap<Vec<u8>, RawStateChangesWithTrieKey>;
248
249#[derive(Debug)]
250pub enum StateChangesRequest {
251    AccountChanges { account_ids: Vec<AccountId> },
252    SingleAccessKeyChanges { keys: Vec<AccountWithPublicKey> },
253    AllAccessKeyChanges { account_ids: Vec<AccountId> },
254    ContractCodeChanges { account_ids: Vec<AccountId> },
255    DataChanges { account_ids: Vec<AccountId>, key_prefix: StoreKey },
256}
257
258#[derive(Debug)]
259pub enum StateChangeValue {
260    AccountUpdate {
261        account_id: AccountId,
262        account: Account,
263    },
264    AccountDeletion {
265        account_id: AccountId,
266    },
267    AccessKeyUpdate {
268        account_id: AccountId,
269        public_key: PublicKey,
270        access_key: AccessKey,
271    },
272    AccessKeyDeletion {
273        account_id: AccountId,
274        public_key: PublicKey,
275    },
276    DataUpdate {
277        account_id: AccountId,
278        key: StoreKey,
279        value: StoreValue,
280    },
281    DataDeletion {
282        account_id: AccountId,
283        key: StoreKey,
284    },
285    ContractCodeUpdate {
286        account_id: AccountId,
287        code: Vec<u8>,
288    },
289    ContractCodeDeletion {
290        account_id: AccountId,
291    },
292    RsaKeyUpdate {
293        account_id: AccountId,
294        public_key: PublicKey,
295        rsa_key: RegisterRsa2048KeysAction,
296    },
297    RsaKeyDeletion {
298        account_id: AccountId,
299        public_key: PublicKey,
300    },
301}
302
303impl StateChangeValue {
304    pub fn affected_account_id(&self) -> &AccountId {
305        match &self {
306            StateChangeValue::AccountUpdate { account_id, .. }
307            | StateChangeValue::AccountDeletion { account_id }
308            | StateChangeValue::AccessKeyUpdate { account_id, .. }
309            | StateChangeValue::AccessKeyDeletion { account_id, .. }
310            | StateChangeValue::DataUpdate { account_id, .. }
311            | StateChangeValue::DataDeletion { account_id, .. }
312            | StateChangeValue::ContractCodeUpdate { account_id, .. }
313            | StateChangeValue::RsaKeyUpdate { account_id, .. }
314            | StateChangeValue::RsaKeyDeletion { account_id, .. }
315            | StateChangeValue::ContractCodeDeletion { account_id } => account_id,
316        }
317    }
318}
319
320#[derive(Debug)]
321pub struct StateChangeWithCause {
322    pub cause: StateChangeCause,
323    pub value: StateChangeValue,
324}
325
326pub type StateChanges = Vec<StateChangeWithCause>;
327
328#[easy_ext::ext(StateChangesExt)]
329impl StateChanges {
330    pub fn from_changes(
331        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
332    ) -> Result<StateChanges, std::io::Error> {
333        let mut state_changes = Self::new();
334
335        for raw_change in raw_changes {
336            let RawStateChangesWithTrieKey { trie_key, changes } = raw_change?;
337
338            match trie_key {
339                TrieKey::Account { account_id } => state_changes.extend(changes.into_iter().map(
340                    |RawStateChange { cause, data }| StateChangeWithCause {
341                        cause,
342                        value: if let Some(change_data) = data {
343                            StateChangeValue::AccountUpdate {
344                                account_id: account_id.clone(),
345                                account: <_>::try_from_slice(&change_data).expect(
346                                    "Failed to parse internally stored account information",
347                                ),
348                            }
349                        } else {
350                            StateChangeValue::AccountDeletion { account_id: account_id.clone() }
351                        },
352                    },
353                )),
354                TrieKey::AccessKey { account_id, public_key } => {
355                    state_changes.extend(changes.into_iter().map(
356                        |RawStateChange { cause, data }| StateChangeWithCause {
357                            cause,
358                            value: if let Some(change_data) = data {
359                                StateChangeValue::AccessKeyUpdate {
360                                    account_id: account_id.clone(),
361                                    public_key: public_key.clone(),
362                                    access_key: <_>::try_from_slice(&change_data)
363                                        .expect("Failed to parse internally stored access key"),
364                                }
365                            } else {
366                                StateChangeValue::AccessKeyDeletion {
367                                    account_id: account_id.clone(),
368                                    public_key: public_key.clone(),
369                                }
370                            },
371                        },
372                    ))
373                }
374                TrieKey::ContractCode { account_id } => {
375                    state_changes.extend(changes.into_iter().map(
376                        |RawStateChange { cause, data }| StateChangeWithCause {
377                            cause,
378                            value: match data {
379                                Some(change_data) => StateChangeValue::ContractCodeUpdate {
380                                    account_id: account_id.clone(),
381                                    code: change_data,
382                                },
383                                None => StateChangeValue::ContractCodeDeletion {
384                                    account_id: account_id.clone(),
385                                },
386                            },
387                        },
388                    ));
389                }
390                TrieKey::ContractData { account_id, key } => {
391                    state_changes.extend(changes.into_iter().map(
392                        |RawStateChange { cause, data }| StateChangeWithCause {
393                            cause,
394                            value: if let Some(change_data) = data {
395                                StateChangeValue::DataUpdate {
396                                    account_id: account_id.clone(),
397                                    key: key.to_vec().into(),
398                                    value: change_data.into(),
399                                }
400                            } else {
401                                StateChangeValue::DataDeletion {
402                                    account_id: account_id.clone(),
403                                    key: key.to_vec().into(),
404                                }
405                            },
406                        },
407                    ));
408                }
409                // The next variants considered as unnecessary as too low level
410                TrieKey::ReceivedData { .. } => {}
411                TrieKey::PostponedReceiptId { .. } => {}
412                TrieKey::PendingDataCount { .. } => {}
413                TrieKey::PostponedReceipt { .. } => {}
414                TrieKey::DelayedReceiptIndices => {}
415                TrieKey::DelayedReceipt { .. } => {}
416                TrieKey::Rsa2048Keys { account_id, public_key } => {
417                    state_changes.extend(changes.into_iter().map(
418                        |RawStateChange { cause, data }| StateChangeWithCause {
419                            cause,
420                            value: if let Some(change_data) = data {
421                                StateChangeValue::AccessKeyUpdate {
422                                    account_id: account_id.clone(),
423                                    public_key: public_key.clone(),
424                                    access_key: <_>::try_from_slice(&change_data)
425                                        .expect("Failed to parse internally stored access key"),
426                                }
427                            } else {
428                                StateChangeValue::AccessKeyDeletion {
429                                    account_id: account_id.clone(),
430                                    public_key: public_key.clone(),
431                                }
432                            },
433                        },
434                    ))
435                }
436            }
437        }
438
439        Ok(state_changes)
440    }
441    pub fn from_account_changes(
442        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
443    ) -> Result<StateChanges, std::io::Error> {
444        let state_changes = Self::from_changes(raw_changes)?;
445
446        Ok(state_changes
447            .into_iter()
448            .filter(|state_change| {
449                matches!(
450                    state_change.value,
451                    StateChangeValue::AccountUpdate { .. }
452                        | StateChangeValue::AccountDeletion { .. }
453                )
454            })
455            .collect())
456    }
457
458    pub fn from_access_key_changes(
459        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
460    ) -> Result<StateChanges, std::io::Error> {
461        let state_changes = Self::from_changes(raw_changes)?;
462
463        Ok(state_changes
464            .into_iter()
465            .filter(|state_change| {
466                matches!(
467                    state_change.value,
468                    StateChangeValue::AccessKeyUpdate { .. }
469                        | StateChangeValue::AccessKeyDeletion { .. }
470                )
471            })
472            .collect())
473    }
474
475    pub fn from_contract_code_changes(
476        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
477    ) -> Result<StateChanges, std::io::Error> {
478        let state_changes = Self::from_changes(raw_changes)?;
479
480        Ok(state_changes
481            .into_iter()
482            .filter(|state_change| {
483                matches!(
484                    state_change.value,
485                    StateChangeValue::ContractCodeUpdate { .. }
486                        | StateChangeValue::ContractCodeDeletion { .. }
487                )
488            })
489            .collect())
490    }
491
492    pub fn from_data_changes(
493        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
494    ) -> Result<StateChanges, std::io::Error> {
495        let state_changes = Self::from_changes(raw_changes)?;
496
497        Ok(state_changes
498            .into_iter()
499            .filter(|state_change| {
500                matches!(
501                    state_change.value,
502                    StateChangeValue::DataUpdate { .. } | StateChangeValue::DataDeletion { .. }
503                )
504            })
505            .collect())
506    }
507}
508
509#[derive(PartialEq, Eq, Clone, Debug, BorshSerialize, BorshDeserialize, serde::Serialize)]
510pub struct StateRootNode {
511    /// In Nightshade, data is the serialized TrieNodeWithSize.
512    ///
513    /// Beware that hash of an empty state root (i.e. once who’s data is an
514    /// empty byte string) **does not** equal hash of an empty byte string.
515    /// Instead, an all-zero hash indicates an empty node.
516    pub data: Arc<[u8]>,
517
518    /// In Nightshade, memory_usage is a field of TrieNodeWithSize.
519    pub memory_usage: u64,
520}
521
522impl StateRootNode {
523    pub fn empty() -> Self {
524        static EMPTY: Lazy<Arc<[u8]>> = Lazy::new(|| Arc::new([]));
525        StateRootNode { data: EMPTY.clone(), memory_usage: 0 }
526    }
527}
528
529/// Epoch identifier -- wrapped hash, to make it easier to distinguish.
530/// EpochId of epoch T is the hash of last block in T-2
531/// EpochId of first two epochs is 0
532#[derive(
533    Debug,
534    Clone,
535    Default,
536    Hash,
537    Eq,
538    PartialEq,
539    PartialOrd,
540    Ord,
541    derive_more::AsRef,
542    BorshSerialize,
543    BorshDeserialize,
544    serde::Serialize,
545    serde::Deserialize,
546    arbitrary::Arbitrary,
547)]
548#[as_ref(forward)]
549pub struct EpochId(pub CryptoHash);
550
551impl std::str::FromStr for EpochId {
552    type Err = Box<dyn std::error::Error + Send + Sync>;
553
554    /// Decodes base58-encoded string into a 32-byte crypto hash.
555    fn from_str(epoch_id_str: &str) -> Result<Self, Self::Err> {
556        Ok(EpochId(CryptoHash::from_str(epoch_id_str)?))
557    }
558}
559/// TODO
560
561/// TODO
562/// Stores validator and its power for two consecutive epochs.
563/// It is necessary because the blocks on the epoch boundary need to contain approvals from both
564/// epochs.
565#[derive(BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
566pub struct ApprovalPledge {
567    /// Account that has pledge.
568    pub account_id: AccountId,
569    /// Public key of the proposed validator.
570    pub public_key: PublicKey,
571    /// Pledge / weight of the validator.
572    pub pledge_this_epoch: Balance,
573    /// Pledge of the validator.
574    pub pledge_next_epoch: Balance,
575}
576
577pub mod validator_power_and_pledge {
578    use borsh::{BorshDeserialize, BorshSerialize};
579    use serde::Serialize;
580    use unc_crypto::PublicKey;
581    use unc_primitives_core::types::{AccountId, Balance, Power};
582
583    use super::ApprovalPledge;
584    pub use super::ValidatorPowerAndPledgeV1;
585
586    /// Stores validator and its power with pledge.
587    #[derive(
588        BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq, PartialOrd,
589    )]
590    #[serde(tag = "validator_power_and_pledge_struct_version")]
591    pub enum ValidatorPowerAndPledge {
592        V1(ValidatorPowerAndPledgeV1),
593    }
594    #[derive(Clone)]
595    pub struct ValidatorPowerAndPledgeIter<'a> {
596        collection: ValidatorPowerAndPledgeIterSource<'a>,
597        curr_index: usize,
598        len: usize,
599    }
600
601    impl<'a> ValidatorPowerAndPledgeIter<'a> {
602        pub fn empty() -> Self {
603            Self { collection: ValidatorPowerAndPledgeIterSource::V2(&[]), curr_index: 0, len: 0 }
604        }
605
606        pub fn v1(collection: &'a [ValidatorPowerAndPledgeV1]) -> Self {
607            Self {
608                collection: ValidatorPowerAndPledgeIterSource::V1(collection),
609                curr_index: 0,
610                len: collection.len(),
611            }
612        }
613
614        pub fn new(collection: &'a [ValidatorPowerAndPledge]) -> Self {
615            Self {
616                collection: ValidatorPowerAndPledgeIterSource::V2(collection),
617                curr_index: 0,
618                len: collection.len(),
619            }
620        }
621
622        pub fn len(&self) -> usize {
623            self.len
624        }
625    }
626
627    impl<'a> Iterator for ValidatorPowerAndPledgeIter<'a> {
628        type Item = ValidatorPowerAndPledge;
629
630        fn next(&mut self) -> Option<Self::Item> {
631            if self.curr_index < self.len {
632                let item = match self.collection {
633                    ValidatorPowerAndPledgeIterSource::V1(collection) => {
634                        ValidatorPowerAndPledge::V1(collection[self.curr_index].clone())
635                    }
636                    ValidatorPowerAndPledgeIterSource::V2(collection) => {
637                        collection[self.curr_index].clone()
638                    }
639                };
640                self.curr_index += 1;
641                Some(item)
642            } else {
643                None
644            }
645        }
646    }
647    #[derive(Clone)]
648    enum ValidatorPowerAndPledgeIterSource<'a> {
649        V1(&'a [ValidatorPowerAndPledgeV1]),
650        V2(&'a [ValidatorPowerAndPledge]),
651    }
652
653    impl ValidatorPowerAndPledge {
654        pub fn new_v1(
655            account_id: AccountId,
656            public_key: PublicKey,
657            power: Power,
658            pledge: Balance,
659        ) -> Self {
660            Self::V1(ValidatorPowerAndPledgeV1 { account_id, public_key, power, pledge })
661        }
662
663        pub fn new(
664            account_id: AccountId,
665            public_key: PublicKey,
666            power: Power,
667            pledge: Balance,
668        ) -> Self {
669            Self::new_v1(account_id, public_key, power, pledge)
670        }
671
672        pub fn into_v1(self) -> ValidatorPowerAndPledgeV1 {
673            match self {
674                Self::V1(v1) => v1,
675            }
676        }
677
678        #[inline]
679        pub fn account_and_pledge(self) -> (AccountId, Balance) {
680            match self {
681                Self::V1(v1) => (v1.account_id, v1.pledge),
682            }
683        }
684
685        #[inline]
686        pub fn account_and_power(self) -> (AccountId, Power) {
687            match self {
688                Self::V1(v1) => (v1.account_id, v1.power),
689            }
690        }
691
692        #[inline]
693        pub fn destructure(self) -> (AccountId, PublicKey, Power, Balance) {
694            match self {
695                Self::V1(v1) => (v1.account_id, v1.public_key, v1.power, v1.pledge),
696            }
697        }
698
699        #[inline]
700        pub fn take_account_id(self) -> AccountId {
701            match self {
702                Self::V1(v1) => v1.account_id,
703            }
704        }
705
706        #[inline]
707        pub fn account_id(&self) -> &AccountId {
708            match self {
709                Self::V1(v1) => &v1.account_id,
710            }
711        }
712
713        #[inline]
714        pub fn take_public_key(self) -> PublicKey {
715            match self {
716                Self::V1(v1) => v1.public_key,
717            }
718        }
719
720        #[inline]
721        pub fn public_key(&self) -> &PublicKey {
722            match self {
723                Self::V1(v1) => &v1.public_key,
724            }
725        }
726
727        #[inline]
728        pub fn power(&self) -> Power {
729            match self {
730                Self::V1(v1) => v1.power,
731            }
732        }
733
734        #[inline]
735        pub fn power_mut(&mut self) -> &mut Power {
736            match self {
737                Self::V1(v1) => &mut v1.power,
738            }
739        }
740
741        #[inline]
742        pub fn pledge(&self) -> Balance {
743            match self {
744                Self::V1(v1) => v1.pledge,
745            }
746        }
747
748        pub fn get_approval_pledge(&self, is_next_epoch: bool) -> ApprovalPledge {
749            ApprovalPledge {
750                account_id: self.account_id().clone(),
751                public_key: self.public_key().clone(),
752                pledge_this_epoch: if is_next_epoch { 0 } else { self.pledge() },
753                pledge_next_epoch: if is_next_epoch { self.pledge() } else { 0 },
754            }
755        }
756
757        /// Returns the validator's number of mandates (rounded down) at `pledge_per_seat`.
758        ///
759        /// It returns `u16` since it allows infallible conversion to `usize` and with [`u16::MAX`]
760        /// equalling 65_535 it should be sufficient to hold the number of mandates per validator.
761        ///
762        /// # Why `u16` should be sufficient
763        ///
764        /// As of October 2023, a [recommended lower bound] for the pledge required per mandate is
765        /// 25k $UNC. At this price, the validator with highest pledge would have 1_888 mandates,
766        /// which is well below `u16::MAX`.
767        ///
768        /// From another point of view, with more than `u16::MAX` mandates for validators, sampling
769        /// mandates might become computationally too expensive. This might trigger an increase in
770        /// the required power per mandate, bringing down the number of mandates per validator.
771        ///
772        /// [recommended lower bound]: https://unc.zulipchat.com/#narrow/stream/407237-pagoda.2Fcore.2Fstateless-validation/topic/validator.20seat.20assignment/unc/393792901
773        ///
774        /// # Panics
775        ///
776        /// Panics if the number of mandates overflows `u16`.
777        pub fn num_mandates(&self, pledge_per_mandate: Balance) -> u16 {
778            // Integer division in Rust returns the floor as described here
779            // https://doc.rust-lang.org/std/primitive.u64.html#method.div_euclid
780            u16::try_from(self.pledge() / pledge_per_mandate)
781                .expect("number of mandats should fit u16")
782        }
783
784        /// Returns the weight attributed to the validator's partial mandate.
785        ///
786        /// A validator has a partial mandate if its power cannot be divided evenly by
787        /// `pledge_per_mandate`. The remainder of that division is the weight of the partial
788        /// mandate.
789        ///
790        /// Due to this definintion a validator has exactly one partial mandate with `0 <= weight <
791        /// power_per_mandate`.
792        ///
793        /// # Example
794        ///
795        /// Let `V` be a validator with power of 12. If `pledge_per_mandate` equals 5 then the weight
796        /// of `V`'s partial mandate is `12 % 5 = 2`.
797        pub fn partial_mandate_weight(&self, pledge_per_mandate: Balance) -> Balance {
798            self.pledge() % pledge_per_mandate
799        }
800    }
801}
802
803pub mod validator_stake {
804    use borsh::{BorshDeserialize, BorshSerialize};
805    use serde::Serialize;
806    use unc_crypto::PublicKey;
807    use unc_primitives_core::types::{AccountId, Balance};
808
809    pub use super::ValidatorPledgeV1;
810
811    /// Stores validator and its pledge.
812    #[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
813    #[serde(tag = "validator_validator_struct_version")]
814    pub enum ValidatorPledge {
815        V1(ValidatorPledgeV1),
816    }
817
818    pub struct ValidatorPledgeIter<'a> {
819        collection: ValidatorPledgeIterSource<'a>,
820        curr_index: usize,
821        len: usize,
822    }
823
824    impl<'a> ValidatorPledgeIter<'a> {
825        pub fn empty() -> Self {
826            Self { collection: ValidatorPledgeIterSource::V2(&[]), curr_index: 0, len: 0 }
827        }
828
829        pub fn v1(collection: &'a [ValidatorPledgeV1]) -> Self {
830            Self {
831                collection: ValidatorPledgeIterSource::V1(collection),
832                curr_index: 0,
833                len: collection.len(),
834            }
835        }
836
837        pub fn new(collection: &'a [ValidatorPledge]) -> Self {
838            Self {
839                collection: ValidatorPledgeIterSource::V2(collection),
840                curr_index: 0,
841                len: collection.len(),
842            }
843        }
844
845        pub fn len(&self) -> usize {
846            self.len
847        }
848    }
849
850    impl<'a> Iterator for ValidatorPledgeIter<'a> {
851        type Item = ValidatorPledge;
852
853        fn next(&mut self) -> Option<Self::Item> {
854            if self.curr_index < self.len {
855                let item = match self.collection {
856                    ValidatorPledgeIterSource::V1(collection) => {
857                        ValidatorPledge::V1(collection[self.curr_index].clone())
858                    }
859                    ValidatorPledgeIterSource::V2(collection) => {
860                        collection[self.curr_index].clone()
861                    }
862                };
863                self.curr_index += 1;
864                Some(item)
865            } else {
866                None
867            }
868        }
869    }
870
871    enum ValidatorPledgeIterSource<'a> {
872        V1(&'a [ValidatorPledgeV1]),
873        V2(&'a [ValidatorPledge]),
874    }
875
876    impl ValidatorPledge {
877        pub fn new_v1(account_id: AccountId, public_key: PublicKey, pledge: Balance) -> Self {
878            Self::V1(ValidatorPledgeV1 { account_id, public_key, pledge })
879        }
880
881        pub fn new(account_id: AccountId, public_key: PublicKey, pledge: Balance) -> Self {
882            Self::new_v1(account_id, public_key, pledge)
883        }
884
885        pub fn into_v1(self) -> ValidatorPledgeV1 {
886            match self {
887                Self::V1(v1) => v1,
888            }
889        }
890
891        #[inline]
892        pub fn account_and_pledge(self) -> (AccountId, Balance) {
893            match self {
894                Self::V1(v1) => (v1.account_id, v1.pledge),
895            }
896        }
897
898        #[inline]
899        pub fn destructure(self) -> (AccountId, PublicKey, Balance) {
900            match self {
901                Self::V1(v1) => (v1.account_id, v1.public_key, v1.pledge),
902            }
903        }
904
905        #[inline]
906        pub fn take_account_id(self) -> AccountId {
907            match self {
908                Self::V1(v1) => v1.account_id,
909            }
910        }
911
912        #[inline]
913        pub fn account_id(&self) -> &AccountId {
914            match self {
915                Self::V1(v1) => &v1.account_id,
916            }
917        }
918
919        #[inline]
920        pub fn take_public_key(self) -> PublicKey {
921            match self {
922                Self::V1(v1) => v1.public_key,
923            }
924        }
925
926        #[inline]
927        pub fn public_key(&self) -> &PublicKey {
928            match self {
929                Self::V1(v1) => &v1.public_key,
930            }
931        }
932
933        #[inline]
934        pub fn pledge(&self) -> Balance {
935            match self {
936                Self::V1(v1) => v1.pledge,
937            }
938        }
939
940        #[inline]
941        pub fn pledge_mut(&mut self) -> &mut Balance {
942            match self {
943                Self::V1(v1) => &mut v1.pledge,
944            }
945        }
946    }
947}
948#[derive(BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
949pub struct ApprovalPower {
950    /// Account that has power.
951    pub account_id: AccountId,
952    /// Public key of the proposed validator.
953    pub public_key: PublicKey,
954    /// Power / weight of the validator.
955    pub power_this_epoch: Power,
956    pub power_next_epoch: Power,
957}
958
959pub mod validator_power {
960    use crate::types::ApprovalPower;
961    use borsh::{BorshDeserialize, BorshSerialize};
962    use serde::Serialize;
963    use unc_crypto::PublicKey;
964    use unc_primitives_core::types::{AccountId, Power};
965
966    pub use super::ValidatorPowerV1;
967
968    /// Stores validator and its power.
969    #[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
970    #[serde(tag = "validator_power_struct_version")]
971    pub enum ValidatorPower {
972        V1(ValidatorPowerV1),
973    }
974
975    pub struct ValidatorPowerIter<'a> {
976        collection: ValidatorPowerIterSource<'a>,
977        curr_index: usize,
978        len: usize,
979    }
980
981    impl<'a> ValidatorPowerIter<'a> {
982        pub fn empty() -> Self {
983            Self { collection: ValidatorPowerIterSource::V2(&[]), curr_index: 0, len: 0 }
984        }
985
986        pub fn v1(collection: &'a [ValidatorPowerV1]) -> Self {
987            Self {
988                collection: ValidatorPowerIterSource::V1(collection),
989                curr_index: 0,
990                len: collection.len(),
991            }
992        }
993
994        pub fn new(collection: &'a [ValidatorPower]) -> Self {
995            Self {
996                collection: ValidatorPowerIterSource::V2(collection),
997                curr_index: 0,
998                len: collection.len(),
999            }
1000        }
1001
1002        pub fn len(&self) -> usize {
1003            self.len
1004        }
1005    }
1006
1007    impl<'a> Iterator for ValidatorPowerIter<'a> {
1008        type Item = ValidatorPower;
1009
1010        fn next(&mut self) -> Option<Self::Item> {
1011            if self.curr_index < self.len {
1012                let item = match self.collection {
1013                    ValidatorPowerIterSource::V1(collection) => {
1014                        ValidatorPower::V1(collection[self.curr_index].clone())
1015                    }
1016                    ValidatorPowerIterSource::V2(collection) => collection[self.curr_index].clone(),
1017                };
1018                self.curr_index += 1;
1019                Some(item)
1020            } else {
1021                None
1022            }
1023        }
1024    }
1025
1026    enum ValidatorPowerIterSource<'a> {
1027        V1(&'a [ValidatorPowerV1]),
1028        V2(&'a [ValidatorPower]),
1029    }
1030
1031    impl ValidatorPower {
1032        pub fn new_v1(account_id: AccountId, public_key: PublicKey, power: Power) -> Self {
1033            Self::V1(ValidatorPowerV1 { account_id, public_key, power })
1034        }
1035
1036        pub fn new(account_id: AccountId, public_key: PublicKey, power: Power) -> Self {
1037            Self::new_v1(account_id, public_key, power)
1038        }
1039
1040        pub fn into_v1(self) -> ValidatorPowerV1 {
1041            match self {
1042                Self::V1(v1) => v1,
1043            }
1044        }
1045
1046        #[inline]
1047        pub fn account_and_power(self) -> (AccountId, Power) {
1048            match self {
1049                Self::V1(v1) => (v1.account_id, v1.power),
1050            }
1051        }
1052
1053        #[inline]
1054        pub fn destructure(self) -> (AccountId, PublicKey, Power) {
1055            match self {
1056                Self::V1(v1) => (v1.account_id, v1.public_key, v1.power),
1057            }
1058        }
1059
1060        #[inline]
1061        pub fn take_account_id(self) -> AccountId {
1062            match self {
1063                Self::V1(v1) => v1.account_id,
1064            }
1065        }
1066
1067        #[inline]
1068        pub fn account_id(&self) -> &AccountId {
1069            match self {
1070                Self::V1(v1) => &v1.account_id,
1071            }
1072        }
1073
1074        #[inline]
1075        pub fn take_public_key(self) -> PublicKey {
1076            match self {
1077                Self::V1(v1) => v1.public_key,
1078            }
1079        }
1080
1081        #[inline]
1082        pub fn public_key(&self) -> &PublicKey {
1083            match self {
1084                Self::V1(v1) => &v1.public_key,
1085            }
1086        }
1087
1088        #[inline]
1089        pub fn power(&self) -> Power {
1090            match self {
1091                Self::V1(v1) => v1.power,
1092            }
1093        }
1094
1095        #[inline]
1096        pub fn power_mut(&mut self) -> &mut Power {
1097            match self {
1098                Self::V1(v1) => &mut v1.power,
1099            }
1100        }
1101
1102        pub fn get_approval_power(&self, is_next_epoch: bool) -> ApprovalPower {
1103            ApprovalPower {
1104                account_id: self.account_id().clone(),
1105                public_key: self.public_key().clone(),
1106                power_this_epoch: if is_next_epoch { 0 } else { self.power() },
1107                power_next_epoch: if is_next_epoch { self.power() } else { 0 },
1108            }
1109        }
1110    }
1111}
1112/// Stores validator and its power with pledge.
1113#[derive(
1114    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, PartialOrd,
1115)]
1116pub struct ValidatorPowerAndPledgeV1 {
1117    /// Account that has power.
1118    pub account_id: AccountId,
1119    /// Public key of the proposed validator.
1120    pub public_key: PublicKey,
1121    /// Power / weight of the validator.
1122    pub power: Power,
1123    /// Pledge / weight of the validator.
1124    pub pledge: Balance,
1125}
1126
1127/// Stores validator and its pledge.
1128#[derive(BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
1129pub struct ValidatorPledgeV1 {
1130    /// Account that has pledge.
1131    pub account_id: AccountId,
1132    /// Public key of the proposed validator.
1133    pub public_key: PublicKey,
1134    /// Pledge / weight of the validator.
1135    pub pledge: Balance,
1136}
1137
1138/// Stores validator and its power.
1139#[derive(BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
1140pub struct ValidatorPowerV1 {
1141    /// Account that has power.
1142    pub account_id: AccountId,
1143    /// Public key of the proposed validator.
1144    pub public_key: PublicKey,
1145    /// Power / weight of the validator.
1146    pub power: Power,
1147}
1148
1149/// Information after block was processed.
1150#[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq)]
1151pub struct BlockExtra {
1152    pub challenges_result: ChallengesResult,
1153}
1154
1155pub mod chunk_extra {
1156    use crate::types::validator_power::{ValidatorPower, ValidatorPowerIter};
1157    use crate::types::validator_stake::{ValidatorPledge, ValidatorPledgeIter};
1158    use crate::types::StateRoot;
1159    use borsh::{BorshDeserialize, BorshSerialize};
1160    use unc_primitives_core::hash::CryptoHash;
1161    use unc_primitives_core::types::{Balance, Gas};
1162
1163    pub use super::ChunkExtraV1;
1164
1165    /// Information after chunk was processed, used to produce or check next chunk.
1166    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq)]
1167    pub enum ChunkExtra {
1168        V1(ChunkExtraV1),
1169        V2(ChunkExtraV2),
1170    }
1171
1172    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq)]
1173    pub struct ChunkExtraV2 {
1174        /// Post state root after applying give chunk.
1175        pub state_root: StateRoot,
1176        /// Root of merklizing results of receipts (transactions) execution.
1177        pub outcome_root: CryptoHash,
1178        /// Validator proposals produced by given chunk.
1179        pub validator_power_proposals: Vec<ValidatorPower>,
1180        /// Validator proposals produced by given chunk.
1181        pub validator_pledge_proposals: Vec<ValidatorPledge>,
1182        /// Actually how much gas were used.
1183        pub gas_used: Gas,
1184        /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
1185        pub gas_limit: Gas,
1186        /// Total balance burnt after processing the current chunk.
1187        pub balance_burnt: Balance,
1188    }
1189
1190    impl ChunkExtra {
1191        pub fn new_with_only_state_root(state_root: &StateRoot) -> Self {
1192            Self::new(state_root, CryptoHash::default(), vec![], vec![], 0, 0, 0)
1193        }
1194
1195        pub fn new(
1196            state_root: &StateRoot,
1197            outcome_root: CryptoHash,
1198            validator_power_proposals: Vec<ValidatorPower>,
1199            validator_pledge_proposals: Vec<ValidatorPledge>,
1200            gas_used: Gas,
1201            gas_limit: Gas,
1202            balance_burnt: Balance,
1203        ) -> Self {
1204            Self::V2(ChunkExtraV2 {
1205                state_root: *state_root,
1206                outcome_root,
1207                validator_power_proposals,
1208                validator_pledge_proposals,
1209                gas_used,
1210                gas_limit,
1211                balance_burnt,
1212            })
1213        }
1214
1215        #[inline]
1216        pub fn outcome_root(&self) -> &StateRoot {
1217            match self {
1218                Self::V1(v1) => &v1.outcome_root,
1219                Self::V2(v2) => &v2.outcome_root,
1220            }
1221        }
1222
1223        #[inline]
1224        pub fn state_root(&self) -> &StateRoot {
1225            match self {
1226                Self::V1(v1) => &v1.state_root,
1227                Self::V2(v2) => &v2.state_root,
1228            }
1229        }
1230
1231        #[inline]
1232        pub fn state_root_mut(&mut self) -> &mut StateRoot {
1233            match self {
1234                Self::V1(v1) => &mut v1.state_root,
1235                Self::V2(v2) => &mut v2.state_root,
1236            }
1237        }
1238
1239        #[inline]
1240        pub fn validator_power_proposals(&self) -> ValidatorPowerIter {
1241            match self {
1242                Self::V1(v1) => ValidatorPowerIter::v1(&v1.validator_power_proposals),
1243                Self::V2(v2) => ValidatorPowerIter::new(&v2.validator_power_proposals),
1244            }
1245        }
1246
1247        #[inline]
1248        pub fn validator_pledge_proposals(&self) -> ValidatorPledgeIter {
1249            match self {
1250                Self::V1(v1) => ValidatorPledgeIter::v1(&v1.validator_pledge_proposals),
1251                Self::V2(v2) => ValidatorPledgeIter::new(&v2.validator_pledge_proposals),
1252            }
1253        }
1254
1255        #[inline]
1256        pub fn gas_limit(&self) -> Gas {
1257            match self {
1258                Self::V1(v1) => v1.gas_limit,
1259                Self::V2(v2) => v2.gas_limit,
1260            }
1261        }
1262
1263        #[inline]
1264        pub fn gas_used(&self) -> Gas {
1265            match self {
1266                Self::V1(v1) => v1.gas_used,
1267                Self::V2(v2) => v2.gas_used,
1268            }
1269        }
1270
1271        #[inline]
1272        pub fn balance_burnt(&self) -> Balance {
1273            match self {
1274                Self::V1(v1) => v1.balance_burnt,
1275                Self::V2(v2) => v2.balance_burnt,
1276            }
1277        }
1278    }
1279}
1280
1281/// Information after chunk was processed, used to produce or check next chunk.
1282#[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq)]
1283pub struct ChunkExtraV1 {
1284    /// Post state root after applying give chunk.
1285    pub state_root: StateRoot,
1286    /// Root of merklizing results of receipts (transactions) execution.
1287    pub outcome_root: CryptoHash,
1288    /// Validator proposals produced by given chunk.
1289    pub validator_power_proposals: Vec<ValidatorPowerV1>,
1290    /// Validator proposals produced by given chunk.
1291    pub validator_pledge_proposals: Vec<ValidatorPledgeV1>,
1292    /// Actually how much gas were used.
1293    pub gas_used: Gas,
1294    /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
1295    pub gas_limit: Gas,
1296    /// Total balance burnt after processing the current chunk.
1297    pub balance_burnt: Balance,
1298}
1299
1300#[derive(
1301    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
1302)]
1303#[serde(untagged)]
1304pub enum BlockId {
1305    Height(BlockHeight),
1306    Hash(CryptoHash),
1307}
1308
1309pub type MaybeBlockId = Option<BlockId>;
1310
1311#[derive(
1312    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
1313)]
1314#[serde(rename_all = "snake_case")]
1315pub enum SyncCheckpoint {
1316    Genesis,
1317    EarliestAvailable,
1318}
1319
1320#[derive(
1321    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
1322)]
1323#[serde(rename_all = "snake_case")]
1324pub enum BlockReference {
1325    BlockId(BlockId),
1326    Finality(Finality),
1327    SyncCheckpoint(SyncCheckpoint),
1328}
1329
1330impl BlockReference {
1331    pub fn latest() -> Self {
1332        Self::Finality(Finality::None)
1333    }
1334}
1335
1336impl From<BlockId> for BlockReference {
1337    fn from(block_id: BlockId) -> Self {
1338        Self::BlockId(block_id)
1339    }
1340}
1341
1342impl From<Finality> for BlockReference {
1343    fn from(finality: Finality) -> Self {
1344        Self::Finality(finality)
1345    }
1346}
1347
1348#[derive(Default, BorshSerialize, BorshDeserialize, Clone, Debug, PartialEq, Eq)]
1349pub struct ValidatorStats {
1350    pub produced: NumBlocks,
1351    pub expected: NumBlocks,
1352}
1353
1354#[derive(Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq)]
1355pub struct BlockChunkValidatorStats {
1356    pub block_stats: ValidatorStats,
1357    pub chunk_stats: ValidatorStats,
1358}
1359
1360#[derive(serde::Deserialize, Debug, arbitrary::Arbitrary, PartialEq, Eq)]
1361#[serde(rename_all = "snake_case")]
1362pub enum EpochReference {
1363    EpochId(EpochId),
1364    BlockId(BlockId),
1365    Latest,
1366}
1367
1368impl serde::Serialize for EpochReference {
1369    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
1370    where
1371        S: serde::Serializer,
1372    {
1373        match self {
1374            EpochReference::EpochId(epoch_id) => {
1375                s.serialize_newtype_variant("EpochReference", 0, "epoch_id", epoch_id)
1376            }
1377            EpochReference::BlockId(block_id) => {
1378                s.serialize_newtype_variant("EpochReference", 1, "block_id", block_id)
1379            }
1380            EpochReference::Latest => {
1381                s.serialize_newtype_variant("EpochReference", 2, "latest", &())
1382            }
1383        }
1384    }
1385}
1386
1387/// Either an epoch id or latest block hash.  When `EpochId` variant is used it
1388/// must be an identifier of a past epoch.  When `BlockHeight` is used it must
1389/// be hash of the latest block in the current epoch.  Using current epoch id
1390/// with `EpochId` or arbitrary block hash in past or present epochs will result
1391/// in errors.
1392#[derive(Debug)]
1393pub enum ValidatorInfoIdentifier {
1394    EpochId(EpochId),
1395    BlockHash(CryptoHash),
1396}
1397
1398/// Reasons for removing a validator from the validator set.
1399#[derive(
1400    BorshSerialize,
1401    BorshDeserialize,
1402    serde::Serialize,
1403    serde::Deserialize,
1404    Clone,
1405    Debug,
1406    PartialEq,
1407    Eq,
1408)]
1409pub enum ValidatorKickoutReason {
1410    /// Slashed validators are kicked out.
1411    Slashed,
1412    /// Validator didn't produce enough blocks.
1413    NotEnoughBlocks { produced: NumBlocks, expected: NumBlocks },
1414    /// Validator didn't produce enough chunks.
1415    NotEnoughChunks { produced: NumBlocks, expected: NumBlocks },
1416    /// Validator unpowered themselves.
1417    Unpowered,
1418    /// Validator power is now below threshold
1419    NotEnoughPower {
1420        #[serde(with = "dec_format", rename = "power_u128")]
1421        power: Power,
1422        #[serde(with = "dec_format", rename = "power_threshold_u128")]
1423        threshold: Power,
1424    },
1425    /// Validator unpledge themselves.
1426    Unpledge,
1427    /// Validator pledge is now below threshold
1428    NotEnoughPledge {
1429        #[serde(with = "dec_format", rename = "pledge_u128")]
1430        pledge: Balance,
1431        #[serde(with = "dec_format", rename = "pledge_threshold_u128")]
1432        threshold: Balance,
1433    },
1434    /// Enough power but is not chosen because of seat limits.
1435    DidNotGetASeat,
1436}
1437
1438#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
1439#[serde(tag = "type", rename_all = "snake_case")]
1440pub enum TransactionOrReceiptId {
1441    Transaction { transaction_hash: CryptoHash, sender_id: AccountId },
1442    Receipt { receipt_id: CryptoHash, receiver_id: AccountId },
1443}
1444
1445/// Provides information about current epoch validators.
1446/// Used to break dependency between epoch manager and runtime.
1447pub trait EpochInfoProvider {
1448    /// Get current power of a validator in the given epoch.
1449    /// If the account is not a validator, returns `None`.
1450    fn validator_power(
1451        &self,
1452        epoch_id: &EpochId,
1453        last_block_hash: &CryptoHash,
1454        account_id: &AccountId,
1455    ) -> Result<Option<Power>, EpochError>;
1456
1457    /// Get the total power of the given epoch.
1458    fn validator_total_power(
1459        &self,
1460        epoch_id: &EpochId,
1461        last_block_hash: &CryptoHash,
1462    ) -> Result<Power, EpochError>;
1463
1464    fn minimum_power(&self, prev_block_hash: &CryptoHash) -> Result<Power, EpochError>;
1465
1466    /// Get current pledge of a validator in the given epoch.
1467    /// If the account is not a validator, returns `None`.
1468    fn validator_stake(
1469        &self,
1470        epoch_id: &EpochId,
1471        last_block_hash: &CryptoHash,
1472        account_id: &AccountId,
1473    ) -> Result<Option<Balance>, EpochError>;
1474
1475    /// Get the total pledge of the given epoch.
1476    fn validator_total_stake(
1477        &self,
1478        epoch_id: &EpochId,
1479        last_block_hash: &CryptoHash,
1480    ) -> Result<Balance, EpochError>;
1481
1482    fn minimum_pledge(&self, prev_block_hash: &CryptoHash) -> Result<Balance, EpochError>;
1483}
1484
1485/// Mode of the trie cache.
1486#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1487pub enum TrieCacheMode {
1488    /// In this mode we put each visited node to LRU cache to optimize performance.
1489    /// Presence of any exact node is not guaranteed.
1490    CachingShard,
1491    /// In this mode we put each visited node to the chunk cache which is a hash map.
1492    /// This is needed to guarantee that all nodes for which we charged a touching trie node cost are retrieved from DB
1493    /// only once during a single chunk processing. Such nodes remain in cache until the chunk processing is finished,
1494    /// and thus users (potentially different) are not required to pay twice for retrieval of the same node.
1495    CachingChunk,
1496}
1497
1498/// State changes for a range of blocks.
1499/// Expects that a block is present at most once in the list.
1500#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1501pub struct StateChangesForBlockRange {
1502    pub blocks: Vec<StateChangesForBlock>,
1503}
1504
1505/// State changes for a single block.
1506/// Expects that a shard is present at most once in the list of state changes.
1507#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1508pub struct StateChangesForBlock {
1509    pub block_hash: CryptoHash,
1510    pub state_changes: Vec<StateChangesForShard>,
1511}
1512
1513/// Key and value of a StateChanges column.
1514#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1515pub struct StateChangesForShard {
1516    pub shard_id: ShardId,
1517    pub state_changes: Vec<RawStateChangesWithTrieKey>,
1518}
1519
1520#[cfg(test)]
1521mod tests {
1522    use unc_crypto::{KeyType, PublicKey};
1523    use unc_primitives_core::types::{Balance, Power};
1524
1525    use super::validator_power_and_pledge::ValidatorPowerAndPledge;
1526
1527    fn new_validator_power_and_pledge(power: Power, pledge: Balance) -> ValidatorPowerAndPledge {
1528        ValidatorPowerAndPledge::new(
1529            "test_account".parse().unwrap(),
1530            PublicKey::empty(KeyType::ED25519),
1531            power,
1532            pledge,
1533        )
1534    }
1535
1536    #[test]
1537    fn test_validator_power_num_mandates() {
1538        assert_eq!(new_validator_power_and_pledge(0, 0).num_mandates(5), 0);
1539        assert_eq!(new_validator_power_and_pledge(10, 10).num_mandates(5), 2);
1540        assert_eq!(new_validator_power_and_pledge(12, 12).num_mandates(5), 2);
1541    }
1542
1543    #[test]
1544    fn test_validator_partial_mandate_weight() {
1545        assert_eq!(new_validator_power_and_pledge(0, 0).partial_mandate_weight(5), 0);
1546        assert_eq!(new_validator_power_and_pledge(10, 10).partial_mandate_weight(5), 0);
1547        assert_eq!(new_validator_power_and_pledge(12, 12).partial_mandate_weight(5), 2);
1548    }
1549}