near_primitives/
types.rs

1use crate::account::{AccessKey, Account};
2use crate::errors::EpochError;
3use crate::hash::CryptoHash;
4use crate::serialize::dec_format;
5use crate::shard_layout::ShardLayout;
6use crate::trie_key::TrieKey;
7use borsh::{BorshDeserialize, BorshSerialize};
8pub use chunk_validator_stats::ChunkStats;
9use near_crypto::PublicKey;
10/// Reexport primitive types
11pub use near_primitives_core::types::*;
12use near_schema_checker_lib::ProtocolSchema;
13use serde_with::base64::Base64;
14use serde_with::serde_as;
15use std::sync::Arc;
16use std::sync::LazyLock;
17
18mod chunk_validator_stats;
19
20/// Hash used by to store state root.
21pub type StateRoot = CryptoHash;
22
23/// An arbitrary static string to make sure that this struct cannot be
24/// serialized to look identical to another serialized struct. For chunk
25/// production we are signing a chunk hash, so we need to make sure that
26/// this signature means something different.
27///
28/// This is a messy workaround until we know what to do with NEP 483.
29pub(crate) type SignatureDifferentiator = String;
30
31/// Different types of finality.
32#[derive(
33    serde::Serialize, serde::Deserialize, Default, Clone, Debug, PartialEq, Eq, arbitrary::Arbitrary,
34)]
35#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
36pub enum Finality {
37    #[serde(rename = "optimistic")]
38    None,
39    #[serde(rename = "near-final")]
40    DoomSlug,
41    #[serde(rename = "final")]
42    #[default]
43    Final,
44}
45
46#[derive(Debug, serde::Serialize, serde::Deserialize)]
47#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
48pub struct AccountWithPublicKey {
49    pub account_id: AccountId,
50    pub public_key: PublicKey,
51}
52
53/// Account info for validators
54#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Eq, PartialEq)]
55#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
56pub struct AccountInfo {
57    pub account_id: AccountId,
58    pub public_key: PublicKey,
59    #[serde(with = "dec_format")]
60    #[cfg_attr(feature = "schemars", schemars(with = "String"))]
61    pub amount: Balance,
62}
63
64/// This type is used to mark keys (arrays of bytes) that are queried from store.
65///
66/// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently
67/// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`).
68#[serde_as]
69#[derive(
70    serde::Serialize,
71    serde::Deserialize,
72    Clone,
73    Debug,
74    PartialEq,
75    Eq,
76    derive_more::Deref,
77    derive_more::From,
78    derive_more::Into,
79    BorshSerialize,
80    BorshDeserialize,
81)]
82#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
83#[serde(transparent)]
84pub struct StoreKey(
85    #[serde_as(as = "Base64")]
86    #[cfg_attr(feature = "schemars", schemars(schema_with = "crate::serialize::base64_schema"))]
87    Vec<u8>,
88);
89
90/// This type is used to mark values returned from store (arrays of bytes).
91///
92/// NOTE: Currently, this type is only used in the view_client and RPC to be able to transparently
93/// pretty-serialize the bytes arrays as base64-encoded strings (see `serialize.rs`).
94#[serde_as]
95#[derive(
96    serde::Serialize,
97    serde::Deserialize,
98    Clone,
99    Debug,
100    PartialEq,
101    Eq,
102    derive_more::Deref,
103    derive_more::From,
104    derive_more::Into,
105    BorshSerialize,
106    BorshDeserialize,
107)]
108#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
109#[serde(transparent)]
110pub struct StoreValue(
111    #[serde_as(as = "Base64")]
112    #[cfg_attr(feature = "schemars", schemars(schema_with = "crate::serialize::base64_schema"))]
113    Vec<u8>,
114);
115
116/// This type is used to mark function arguments.
117///
118/// NOTE: The main reason for this to exist (except the type-safety) is that the value is
119/// transparently serialized and deserialized as a base64-encoded string when serde is used
120/// (serde_json).
121#[serde_as]
122#[derive(
123    serde::Serialize,
124    serde::Deserialize,
125    Clone,
126    Debug,
127    PartialEq,
128    Eq,
129    derive_more::Deref,
130    derive_more::From,
131    derive_more::Into,
132    BorshSerialize,
133    BorshDeserialize,
134)]
135#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
136#[serde(transparent)]
137pub struct FunctionArgs(
138    #[serde_as(as = "Base64")]
139    #[cfg_attr(feature = "schemars", schemars(schema_with = "crate::serialize::base64_schema"))]
140    Vec<u8>,
141);
142
143/// A structure used to indicate the kind of state changes due to transaction/receipt processing, etc.
144#[derive(Debug, Clone)]
145pub enum StateChangeKind {
146    AccountTouched { account_id: AccountId },
147    AccessKeyTouched { account_id: AccountId },
148    DataTouched { account_id: AccountId },
149    ContractCodeTouched { account_id: AccountId },
150}
151
152pub type StateChangesKinds = Vec<StateChangeKind>;
153
154#[easy_ext::ext(StateChangesKindsExt)]
155impl StateChangesKinds {
156    pub fn from_changes(
157        raw_changes: &mut dyn Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
158    ) -> Result<StateChangesKinds, std::io::Error> {
159        raw_changes
160            .filter_map(|raw_change| {
161                let RawStateChangesWithTrieKey { trie_key, .. } = match raw_change {
162                    Ok(p) => p,
163                    Err(e) => return Some(Err(e)),
164                };
165                match trie_key {
166                    TrieKey::Account { account_id } => {
167                        Some(Ok(StateChangeKind::AccountTouched { account_id }))
168                    }
169                    TrieKey::ContractCode { account_id } => {
170                        Some(Ok(StateChangeKind::ContractCodeTouched { account_id }))
171                    }
172                    TrieKey::AccessKey { account_id, .. } => {
173                        Some(Ok(StateChangeKind::AccessKeyTouched { account_id }))
174                    }
175                    TrieKey::ContractData { account_id, .. } => {
176                        Some(Ok(StateChangeKind::DataTouched { account_id }))
177                    }
178                    _ => None,
179                }
180            })
181            .collect()
182    }
183}
184
185/// A structure used to index state changes due to transaction/receipt processing and other things.
186#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, ProtocolSchema)]
187pub enum StateChangeCause {
188    /// A type of update that does not get finalized. Used for verification and execution of
189    /// immutable smart contract methods. Attempt fo finalize a `TrieUpdate` containing such
190    /// change will lead to panic.
191    NotWritableToDisk,
192    /// A type of update that is used to mark the initial storage update, e.g. during genesis
193    /// or in tests setup.
194    InitialState,
195    /// Processing of a transaction.
196    TransactionProcessing { tx_hash: CryptoHash },
197    /// Before the receipt is going to be processed, inputs get drained from the state, which
198    /// causes state modification.
199    ActionReceiptProcessingStarted { receipt_hash: CryptoHash },
200    /// Computation of gas reward.
201    ActionReceiptGasReward { receipt_hash: CryptoHash },
202    /// Processing of a receipt.
203    ReceiptProcessing { receipt_hash: CryptoHash },
204    /// The given receipt was postponed. This is either a data receipt or an action receipt.
205    /// A `DataReceipt` can be postponed if the corresponding `ActionReceipt` is not received yet,
206    /// or other data dependencies are not satisfied.
207    /// An `ActionReceipt` can be postponed if not all data dependencies are received.
208    PostponedReceipt { receipt_hash: CryptoHash },
209    /// Updated delayed receipts queue in the state.
210    /// We either processed previously delayed receipts or added more receipts to the delayed queue.
211    UpdatedDelayedReceipts,
212    /// State change that happens when we update validator accounts. Not associated with any
213    /// specific transaction or receipt.
214    ValidatorAccountsUpdate,
215    /// State change that is happens due to migration that happens in first block of an epoch
216    /// after protocol upgrade
217    Migration,
218    /// Deprecated in #13155, we need to keep it to preserve enum variant tags for borsh serialization.
219    _UnusedReshardingV2,
220    /// Update persistent state kept by Bandwidth Scheduler after running the scheduling algorithm.
221    BandwidthSchedulerStateUpdate,
222}
223
224/// This represents the committed changes in the Trie with a change cause.
225#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, ProtocolSchema)]
226pub struct RawStateChange {
227    pub cause: StateChangeCause,
228    pub data: Option<Vec<u8>>,
229}
230
231/// List of committed changes with a cause for a given TrieKey
232#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, ProtocolSchema)]
233pub struct RawStateChangesWithTrieKey {
234    pub trie_key: TrieKey,
235    pub changes: Vec<RawStateChange>,
236}
237
238/// Consolidate state change of trie_key and the final value the trie key will be changed to
239#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, ProtocolSchema)]
240pub struct ConsolidatedStateChange {
241    pub trie_key: TrieKey,
242    pub value: Option<Vec<u8>>,
243}
244
245/// key that was updated -> list of updates with the corresponding indexing event.
246pub type RawStateChanges = std::collections::BTreeMap<Vec<u8>, RawStateChangesWithTrieKey>;
247
248#[derive(Debug)]
249pub enum StateChangesRequest {
250    AccountChanges { account_ids: Vec<AccountId> },
251    SingleAccessKeyChanges { keys: Vec<AccountWithPublicKey> },
252    AllAccessKeyChanges { account_ids: Vec<AccountId> },
253    ContractCodeChanges { account_ids: Vec<AccountId> },
254    DataChanges { account_ids: Vec<AccountId>, key_prefix: StoreKey },
255}
256
257#[derive(Debug)]
258pub enum StateChangeValue {
259    AccountUpdate { account_id: AccountId, account: Account },
260    AccountDeletion { account_id: AccountId },
261    AccessKeyUpdate { account_id: AccountId, public_key: PublicKey, access_key: AccessKey },
262    AccessKeyDeletion { account_id: AccountId, public_key: PublicKey },
263    DataUpdate { account_id: AccountId, key: StoreKey, value: StoreValue },
264    DataDeletion { account_id: AccountId, key: StoreKey },
265    ContractCodeUpdate { account_id: AccountId, code: Vec<u8> },
266    ContractCodeDeletion { account_id: AccountId },
267}
268
269impl StateChangeValue {
270    pub fn affected_account_id(&self) -> &AccountId {
271        match &self {
272            StateChangeValue::AccountUpdate { account_id, .. }
273            | StateChangeValue::AccountDeletion { account_id }
274            | StateChangeValue::AccessKeyUpdate { account_id, .. }
275            | StateChangeValue::AccessKeyDeletion { account_id, .. }
276            | StateChangeValue::DataUpdate { account_id, .. }
277            | StateChangeValue::DataDeletion { account_id, .. }
278            | StateChangeValue::ContractCodeUpdate { account_id, .. }
279            | StateChangeValue::ContractCodeDeletion { account_id } => account_id,
280        }
281    }
282}
283
284#[derive(Debug)]
285pub struct StateChangeWithCause {
286    pub cause: StateChangeCause,
287    pub value: StateChangeValue,
288}
289
290pub type StateChanges = Vec<StateChangeWithCause>;
291
292#[easy_ext::ext(StateChangesExt)]
293impl StateChanges {
294    pub fn from_changes(
295        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
296    ) -> Result<StateChanges, std::io::Error> {
297        let mut state_changes = Self::new();
298
299        for raw_change in raw_changes {
300            let RawStateChangesWithTrieKey { trie_key, changes } = raw_change?;
301
302            match trie_key {
303                TrieKey::Account { account_id } => state_changes.extend(changes.into_iter().map(
304                    |RawStateChange { cause, data }| StateChangeWithCause {
305                        cause,
306                        value: if let Some(change_data) = data {
307                            StateChangeValue::AccountUpdate {
308                                account_id: account_id.clone(),
309                                account: <_>::try_from_slice(&change_data).expect(
310                                    "Failed to parse internally stored account information",
311                                ),
312                            }
313                        } else {
314                            StateChangeValue::AccountDeletion { account_id: account_id.clone() }
315                        },
316                    },
317                )),
318                TrieKey::AccessKey { account_id, public_key } => {
319                    state_changes.extend(changes.into_iter().map(
320                        |RawStateChange { cause, data }| StateChangeWithCause {
321                            cause,
322                            value: if let Some(change_data) = data {
323                                StateChangeValue::AccessKeyUpdate {
324                                    account_id: account_id.clone(),
325                                    public_key: public_key.clone(),
326                                    access_key: <_>::try_from_slice(&change_data)
327                                        .expect("Failed to parse internally stored access key"),
328                                }
329                            } else {
330                                StateChangeValue::AccessKeyDeletion {
331                                    account_id: account_id.clone(),
332                                    public_key: public_key.clone(),
333                                }
334                            },
335                        },
336                    ))
337                }
338                TrieKey::ContractCode { account_id } => {
339                    state_changes.extend(changes.into_iter().map(
340                        |RawStateChange { cause, data }| StateChangeWithCause {
341                            cause,
342                            value: match data {
343                                Some(change_data) => StateChangeValue::ContractCodeUpdate {
344                                    account_id: account_id.clone(),
345                                    code: change_data,
346                                },
347                                None => StateChangeValue::ContractCodeDeletion {
348                                    account_id: account_id.clone(),
349                                },
350                            },
351                        },
352                    ));
353                }
354                TrieKey::ContractData { account_id, 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::DataUpdate {
360                                    account_id: account_id.clone(),
361                                    key: key.to_vec().into(),
362                                    value: change_data.into(),
363                                }
364                            } else {
365                                StateChangeValue::DataDeletion {
366                                    account_id: account_id.clone(),
367                                    key: key.to_vec().into(),
368                                }
369                            },
370                        },
371                    ));
372                }
373                // The next variants considered as unnecessary as too low level
374                TrieKey::ReceivedData { .. } => {}
375                TrieKey::PostponedReceiptId { .. } => {}
376                TrieKey::PendingDataCount { .. } => {}
377                TrieKey::PostponedReceipt { .. } => {}
378                TrieKey::DelayedReceiptIndices => {}
379                TrieKey::DelayedReceipt { .. } => {}
380                TrieKey::PromiseYieldIndices => {}
381                TrieKey::PromiseYieldTimeout { .. } => {}
382                TrieKey::PromiseYieldReceipt { .. } => {}
383                TrieKey::BufferedReceiptIndices => {}
384                TrieKey::BufferedReceipt { .. } => {}
385                TrieKey::BandwidthSchedulerState => {}
386                TrieKey::BufferedReceiptGroupsQueueData { .. } => {}
387                TrieKey::BufferedReceiptGroupsQueueItem { .. } => {}
388                // Global contract code is not a part of account, so ignoring it as well.
389                TrieKey::GlobalContractCode { .. } => {}
390            }
391        }
392
393        Ok(state_changes)
394    }
395    pub fn from_account_changes(
396        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
397    ) -> Result<StateChanges, std::io::Error> {
398        let state_changes = Self::from_changes(raw_changes)?;
399
400        Ok(state_changes
401            .into_iter()
402            .filter(|state_change| {
403                matches!(
404                    state_change.value,
405                    StateChangeValue::AccountUpdate { .. }
406                        | StateChangeValue::AccountDeletion { .. }
407                )
408            })
409            .collect())
410    }
411
412    pub fn from_access_key_changes(
413        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
414    ) -> Result<StateChanges, std::io::Error> {
415        let state_changes = Self::from_changes(raw_changes)?;
416
417        Ok(state_changes
418            .into_iter()
419            .filter(|state_change| {
420                matches!(
421                    state_change.value,
422                    StateChangeValue::AccessKeyUpdate { .. }
423                        | StateChangeValue::AccessKeyDeletion { .. }
424                )
425            })
426            .collect())
427    }
428
429    pub fn from_contract_code_changes(
430        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
431    ) -> Result<StateChanges, std::io::Error> {
432        let state_changes = Self::from_changes(raw_changes)?;
433
434        Ok(state_changes
435            .into_iter()
436            .filter(|state_change| {
437                matches!(
438                    state_change.value,
439                    StateChangeValue::ContractCodeUpdate { .. }
440                        | StateChangeValue::ContractCodeDeletion { .. }
441                )
442            })
443            .collect())
444    }
445
446    pub fn from_data_changes(
447        raw_changes: impl Iterator<Item = Result<RawStateChangesWithTrieKey, std::io::Error>>,
448    ) -> Result<StateChanges, std::io::Error> {
449        let state_changes = Self::from_changes(raw_changes)?;
450
451        Ok(state_changes
452            .into_iter()
453            .filter(|state_change| {
454                matches!(
455                    state_change.value,
456                    StateChangeValue::DataUpdate { .. } | StateChangeValue::DataDeletion { .. }
457                )
458            })
459            .collect())
460    }
461}
462
463#[derive(
464    PartialEq, Eq, Clone, Debug, BorshSerialize, BorshDeserialize, serde::Serialize, ProtocolSchema,
465)]
466pub struct StateRootNode {
467    /// In Nightshade, data is the serialized TrieNodeWithSize.
468    ///
469    /// Beware that hash of an empty state root (i.e. once who’s data is an
470    /// empty byte string) **does not** equal hash of an empty byte string.
471    /// Instead, an all-zero hash indicates an empty node.
472    pub data: Arc<[u8]>,
473
474    /// In Nightshade, memory_usage is a field of TrieNodeWithSize.
475    pub memory_usage: u64,
476}
477
478impl StateRootNode {
479    pub fn empty() -> Self {
480        static EMPTY: LazyLock<Arc<[u8]>> = LazyLock::new(|| Arc::new([]));
481        StateRootNode { data: EMPTY.clone(), memory_usage: 0 }
482    }
483}
484
485/// Epoch identifier -- wrapped hash, to make it easier to distinguish.
486/// EpochId of epoch T is the hash of last block in T-2
487/// EpochId of first two epochs is 0
488#[derive(
489    Debug,
490    Clone,
491    Copy,
492    Default,
493    Hash,
494    Eq,
495    PartialEq,
496    PartialOrd,
497    Ord,
498    derive_more::AsRef,
499    BorshSerialize,
500    BorshDeserialize,
501    serde::Serialize,
502    serde::Deserialize,
503    arbitrary::Arbitrary,
504    ProtocolSchema,
505)]
506#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
507#[as_ref(forward)]
508pub struct EpochId(pub CryptoHash);
509
510impl std::str::FromStr for EpochId {
511    type Err = Box<dyn std::error::Error + Send + Sync>;
512
513    /// Decodes base58-encoded string into a 32-byte crypto hash.
514    fn from_str(epoch_id_str: &str) -> Result<Self, Self::Err> {
515        Ok(EpochId(CryptoHash::from_str(epoch_id_str)?))
516    }
517}
518
519/// Stores validator and its stake for two consecutive epochs.
520/// It is necessary because the blocks on the epoch boundary need to contain approvals from both
521/// epochs.
522#[derive(serde::Serialize, Debug, Clone, PartialEq, Eq)]
523pub struct ApprovalStake {
524    /// Account that stakes money.
525    pub account_id: AccountId,
526    /// Public key of the proposed validator.
527    pub public_key: PublicKey,
528    /// Stake / weight of the validator.
529    pub stake_this_epoch: Balance,
530    pub stake_next_epoch: Balance,
531}
532
533pub mod validator_stake {
534    use crate::types::ApprovalStake;
535    use borsh::{BorshDeserialize, BorshSerialize};
536    use near_crypto::{KeyType, PublicKey};
537    use near_primitives_core::types::{AccountId, Balance};
538    use serde::Serialize;
539
540    pub use super::ValidatorStakeV1;
541
542    /// Stores validator and its stake.
543    #[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
544    #[serde(tag = "validator_stake_struct_version")]
545    pub enum ValidatorStake {
546        V1(ValidatorStakeV1),
547        // Warning: if you're adding a new version, make sure that the borsh encoding of
548        // any `ValidatorStake` cannot be equal to the borsh encoding of any `ValidatorStakeV1`.
549        // See `EpochSyncProofEpochData::use_versioned_bp_hash_format` for an explanation.
550        // The simplest way to ensure that is to make sure that any new `ValidatorStakeVx`
551        // begins with a field of type `AccountId`.
552    }
553
554    pub struct ValidatorStakeIter<'a> {
555        collection: ValidatorStakeIterSource<'a>,
556        curr_index: usize,
557        len: usize,
558    }
559
560    impl<'a> ValidatorStakeIter<'a> {
561        pub fn empty() -> Self {
562            Self { collection: ValidatorStakeIterSource::V2(&[]), curr_index: 0, len: 0 }
563        }
564
565        pub fn v1(collection: &'a [ValidatorStakeV1]) -> Self {
566            Self {
567                collection: ValidatorStakeIterSource::V1(collection),
568                curr_index: 0,
569                len: collection.len(),
570            }
571        }
572
573        pub fn new(collection: &'a [ValidatorStake]) -> Self {
574            Self {
575                collection: ValidatorStakeIterSource::V2(collection),
576                curr_index: 0,
577                len: collection.len(),
578            }
579        }
580
581        pub fn len(&self) -> usize {
582            self.len
583        }
584    }
585
586    impl<'a> Iterator for ValidatorStakeIter<'a> {
587        type Item = ValidatorStake;
588
589        fn next(&mut self) -> Option<Self::Item> {
590            if self.curr_index < self.len {
591                let item = match self.collection {
592                    ValidatorStakeIterSource::V1(collection) => {
593                        ValidatorStake::V1(collection[self.curr_index].clone())
594                    }
595                    ValidatorStakeIterSource::V2(collection) => collection[self.curr_index].clone(),
596                };
597                self.curr_index += 1;
598                Some(item)
599            } else {
600                None
601            }
602        }
603    }
604
605    enum ValidatorStakeIterSource<'a> {
606        V1(&'a [ValidatorStakeV1]),
607        V2(&'a [ValidatorStake]),
608    }
609
610    impl ValidatorStake {
611        pub fn new_v1(account_id: AccountId, public_key: PublicKey, stake: Balance) -> Self {
612            Self::V1(ValidatorStakeV1 { account_id, public_key, stake })
613        }
614
615        pub fn new(account_id: AccountId, public_key: PublicKey, stake: Balance) -> Self {
616            Self::new_v1(account_id, public_key, stake)
617        }
618
619        pub fn test(account_id: AccountId) -> Self {
620            Self::new_v1(account_id, PublicKey::empty(KeyType::ED25519), 0)
621        }
622
623        pub fn into_v1(self) -> ValidatorStakeV1 {
624            match self {
625                Self::V1(v1) => v1,
626            }
627        }
628
629        #[inline]
630        pub fn account_and_stake(self) -> (AccountId, Balance) {
631            match self {
632                Self::V1(v1) => (v1.account_id, v1.stake),
633            }
634        }
635
636        #[inline]
637        pub fn destructure(self) -> (AccountId, PublicKey, Balance) {
638            match self {
639                Self::V1(v1) => (v1.account_id, v1.public_key, v1.stake),
640            }
641        }
642
643        #[inline]
644        pub fn take_account_id(self) -> AccountId {
645            match self {
646                Self::V1(v1) => v1.account_id,
647            }
648        }
649
650        #[inline]
651        pub fn account_id(&self) -> &AccountId {
652            match self {
653                Self::V1(v1) => &v1.account_id,
654            }
655        }
656
657        #[inline]
658        pub fn take_public_key(self) -> PublicKey {
659            match self {
660                Self::V1(v1) => v1.public_key,
661            }
662        }
663
664        #[inline]
665        pub fn public_key(&self) -> &PublicKey {
666            match self {
667                Self::V1(v1) => &v1.public_key,
668            }
669        }
670
671        #[inline]
672        pub fn stake(&self) -> Balance {
673            match self {
674                Self::V1(v1) => v1.stake,
675            }
676        }
677
678        #[inline]
679        pub fn stake_mut(&mut self) -> &mut Balance {
680            match self {
681                Self::V1(v1) => &mut v1.stake,
682            }
683        }
684
685        pub fn get_approval_stake(&self, is_next_epoch: bool) -> ApprovalStake {
686            ApprovalStake {
687                account_id: self.account_id().clone(),
688                public_key: self.public_key().clone(),
689                stake_this_epoch: if is_next_epoch { 0 } else { self.stake() },
690                stake_next_epoch: if is_next_epoch { self.stake() } else { 0 },
691            }
692        }
693
694        /// Returns the validator's number of mandates (rounded down) at `stake_per_seat`.
695        ///
696        /// It returns `u16` since it allows infallible conversion to `usize` and with [`u16::MAX`]
697        /// equalling 65_535 it should be sufficient to hold the number of mandates per validator.
698        ///
699        /// # Why `u16` should be sufficient
700        ///
701        /// As of October 2023, a [recommended lower bound] for the stake required per mandate is
702        /// 25k $NEAR. At this price, the validator with highest stake would have 1_888 mandates,
703        /// which is well below `u16::MAX`.
704        ///
705        /// From another point of view, with more than `u16::MAX` mandates for validators, sampling
706        /// mandates might become computationally too expensive. This might trigger an increase in
707        /// the required stake per mandate, bringing down the number of mandates per validator.
708        ///
709        /// [recommended lower bound]: https://near.zulipchat.com/#narrow/stream/407237-pagoda.2Fcore.2Fstateless-validation/topic/validator.20seat.20assignment/near/393792901
710        ///
711        /// # Panics
712        ///
713        /// Panics if the number of mandates overflows `u16`.
714        pub fn num_mandates(&self, stake_per_mandate: Balance) -> u16 {
715            // Integer division in Rust returns the floor as described here
716            // https://doc.rust-lang.org/std/primitive.u64.html#method.div_euclid
717            u16::try_from(self.stake() / stake_per_mandate)
718                .expect("number of mandates should fit u16")
719        }
720
721        /// Returns the weight attributed to the validator's partial mandate.
722        ///
723        /// A validator has a partial mandate if its stake cannot be divided evenly by
724        /// `stake_per_mandate`. The remainder of that division is the weight of the partial
725        /// mandate.
726        ///
727        /// Due to this definition a validator has exactly one partial mandate with `0 <= weight <
728        /// stake_per_mandate`.
729        ///
730        /// # Example
731        ///
732        /// Let `V` be a validator with stake of 12. If `stake_per_mandate` equals 5 then the weight
733        /// of `V`'s partial mandate is `12 % 5 = 2`.
734        pub fn partial_mandate_weight(&self, stake_per_mandate: Balance) -> Balance {
735            self.stake() % stake_per_mandate
736        }
737    }
738}
739
740/// Stores validator and its stake.
741#[derive(
742    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, ProtocolSchema,
743)]
744pub struct ValidatorStakeV1 {
745    /// Account that stakes money.
746    pub account_id: AccountId,
747    /// Public key of the proposed validator.
748    pub public_key: PublicKey,
749    /// Stake / weight of the validator.
750    pub stake: Balance,
751}
752
753pub mod chunk_extra {
754    use crate::bandwidth_scheduler::BandwidthRequests;
755    use crate::congestion_info::CongestionInfo;
756    use crate::types::StateRoot;
757    use crate::types::validator_stake::{ValidatorStake, ValidatorStakeIter};
758    use borsh::{BorshDeserialize, BorshSerialize};
759    use near_primitives_core::hash::CryptoHash;
760    use near_primitives_core::types::{Balance, Gas};
761
762    pub use super::ChunkExtraV1;
763
764    /// Information after chunk was processed, used to produce or check next chunk.
765    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq, serde::Serialize)]
766    pub enum ChunkExtra {
767        V1(ChunkExtraV1),
768        V2(ChunkExtraV2),
769        V3(ChunkExtraV3),
770        V4(ChunkExtraV4),
771    }
772
773    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq, serde::Serialize)]
774    pub struct ChunkExtraV2 {
775        /// Post state root after applying give chunk.
776        pub state_root: StateRoot,
777        /// Root of merklizing results of receipts (transactions) execution.
778        pub outcome_root: CryptoHash,
779        /// Validator proposals produced by given chunk.
780        pub validator_proposals: Vec<ValidatorStake>,
781        /// Actually how much gas were used.
782        pub gas_used: Gas,
783        /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
784        pub gas_limit: Gas,
785        /// Total balance burnt after processing the current chunk.
786        pub balance_burnt: Balance,
787    }
788
789    /// V2 -> V3: add congestion info fields.
790    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq, serde::Serialize)]
791    pub struct ChunkExtraV3 {
792        /// Post state root after applying give chunk.
793        pub state_root: StateRoot,
794        /// Root of merklizing results of receipts (transactions) execution.
795        pub outcome_root: CryptoHash,
796        /// Validator proposals produced by given chunk.
797        pub validator_proposals: Vec<ValidatorStake>,
798        /// Actually how much gas were used.
799        pub gas_used: Gas,
800        /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
801        pub gas_limit: Gas,
802        /// Total balance burnt after processing the current chunk.
803        pub balance_burnt: Balance,
804        /// Congestion info about this shard after the chunk was applied.
805        congestion_info: CongestionInfo,
806    }
807
808    /// V3 -> V4: add bandwidth requests field.
809    #[derive(Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq, serde::Serialize)]
810    pub struct ChunkExtraV4 {
811        /// Post state root after applying give chunk.
812        pub state_root: StateRoot,
813        /// Root of merklizing results of receipts (transactions) execution.
814        pub outcome_root: CryptoHash,
815        /// Validator proposals produced by given chunk.
816        pub validator_proposals: Vec<ValidatorStake>,
817        /// Actually how much gas were used.
818        pub gas_used: Gas,
819        /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
820        pub gas_limit: Gas,
821        /// Total balance burnt after processing the current chunk.
822        pub balance_burnt: Balance,
823        /// Congestion info about this shard after the chunk was applied.
824        congestion_info: CongestionInfo,
825        /// Requests for bandwidth to send receipts to other shards.
826        pub bandwidth_requests: BandwidthRequests,
827    }
828
829    impl ChunkExtra {
830        /// This method creates a slimmed down and invalid ChunkExtra. It's used
831        /// for resharding where we only need the state root. This should not be
832        /// used as part of regular processing.
833        pub fn new_with_only_state_root(state_root: &StateRoot) -> Self {
834            // TODO(congestion_control) - integration with resharding
835            let congestion_control = Some(CongestionInfo::default());
836            Self::new(
837                state_root,
838                CryptoHash::default(),
839                vec![],
840                0,
841                0,
842                0,
843                congestion_control,
844                BandwidthRequests::empty(),
845            )
846        }
847
848        pub fn new(
849            state_root: &StateRoot,
850            outcome_root: CryptoHash,
851            validator_proposals: Vec<ValidatorStake>,
852            gas_used: Gas,
853            gas_limit: Gas,
854            balance_burnt: Balance,
855            congestion_info: Option<CongestionInfo>,
856            bandwidth_requests: BandwidthRequests,
857        ) -> Self {
858            Self::V4(ChunkExtraV4 {
859                state_root: *state_root,
860                outcome_root,
861                validator_proposals,
862                gas_used,
863                gas_limit,
864                balance_burnt,
865                congestion_info: congestion_info.unwrap(),
866                bandwidth_requests,
867            })
868        }
869
870        #[inline]
871        pub fn outcome_root(&self) -> &StateRoot {
872            match self {
873                Self::V1(v1) => &v1.outcome_root,
874                Self::V2(v2) => &v2.outcome_root,
875                Self::V3(v3) => &v3.outcome_root,
876                Self::V4(v4) => &v4.outcome_root,
877            }
878        }
879
880        #[inline]
881        pub fn state_root(&self) -> &StateRoot {
882            match self {
883                Self::V1(v1) => &v1.state_root,
884                Self::V2(v2) => &v2.state_root,
885                Self::V3(v3) => &v3.state_root,
886                Self::V4(v4) => &v4.state_root,
887            }
888        }
889
890        #[inline]
891        pub fn state_root_mut(&mut self) -> &mut StateRoot {
892            match self {
893                Self::V1(v1) => &mut v1.state_root,
894                Self::V2(v2) => &mut v2.state_root,
895                Self::V3(v3) => &mut v3.state_root,
896                Self::V4(v4) => &mut v4.state_root,
897            }
898        }
899
900        #[inline]
901        pub fn validator_proposals(&self) -> ValidatorStakeIter {
902            match self {
903                Self::V1(v1) => ValidatorStakeIter::v1(&v1.validator_proposals),
904                Self::V2(v2) => ValidatorStakeIter::new(&v2.validator_proposals),
905                Self::V3(v3) => ValidatorStakeIter::new(&v3.validator_proposals),
906                Self::V4(v4) => ValidatorStakeIter::new(&v4.validator_proposals),
907            }
908        }
909
910        #[inline]
911        pub fn gas_limit(&self) -> Gas {
912            match self {
913                Self::V1(v1) => v1.gas_limit,
914                Self::V2(v2) => v2.gas_limit,
915                Self::V3(v3) => v3.gas_limit,
916                Self::V4(v4) => v4.gas_limit,
917            }
918        }
919
920        #[inline]
921        pub fn gas_used(&self) -> Gas {
922            match self {
923                Self::V1(v1) => v1.gas_used,
924                Self::V2(v2) => v2.gas_used,
925                Self::V3(v3) => v3.gas_used,
926                Self::V4(v4) => v4.gas_used,
927            }
928        }
929
930        #[inline]
931        pub fn balance_burnt(&self) -> Balance {
932            match self {
933                Self::V1(v1) => v1.balance_burnt,
934                Self::V2(v2) => v2.balance_burnt,
935                Self::V3(v3) => v3.balance_burnt,
936                Self::V4(v4) => v4.balance_burnt,
937            }
938        }
939
940        #[inline]
941        pub fn congestion_info(&self) -> CongestionInfo {
942            match self {
943                Self::V1(_) | Self::V2(_) => {
944                    debug_assert!(false, "Calling congestion_info on V1 or V2 header version");
945                    Default::default()
946                }
947                Self::V3(v3) => v3.congestion_info,
948                Self::V4(v4) => v4.congestion_info,
949            }
950        }
951
952        #[inline]
953        pub fn congestion_info_mut(&mut self) -> &mut CongestionInfo {
954            match self {
955                Self::V1(_) | Self::V2(_) => panic!("Calling congestion_info_mut on V1 or V2"),
956                Self::V3(v3) => &mut v3.congestion_info,
957                Self::V4(v4) => &mut v4.congestion_info,
958            }
959        }
960
961        #[inline]
962        pub fn bandwidth_requests(&self) -> Option<&BandwidthRequests> {
963            match self {
964                Self::V1(_) | Self::V2(_) | Self::V3(_) => None,
965                Self::V4(extra) => Some(&extra.bandwidth_requests),
966            }
967        }
968    }
969}
970
971/// Information after chunk was processed, used to produce or check next chunk.
972#[derive(
973    Debug, PartialEq, BorshSerialize, BorshDeserialize, Clone, Eq, ProtocolSchema, serde::Serialize,
974)]
975pub struct ChunkExtraV1 {
976    /// Post state root after applying give chunk.
977    pub state_root: StateRoot,
978    /// Root of merklizing results of receipts (transactions) execution.
979    pub outcome_root: CryptoHash,
980    /// Validator proposals produced by given chunk.
981    pub validator_proposals: Vec<ValidatorStakeV1>,
982    /// Actually how much gas were used.
983    pub gas_used: Gas,
984    /// Gas limit, allows to increase or decrease limit based on expected time vs real time for computing the chunk.
985    pub gas_limit: Gas,
986    /// Total balance burnt after processing the current chunk.
987    pub balance_burnt: Balance,
988}
989
990#[derive(
991    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
992)]
993#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
994#[serde(untagged)]
995pub enum BlockId {
996    Height(BlockHeight),
997    Hash(CryptoHash),
998}
999
1000pub type MaybeBlockId = Option<BlockId>;
1001
1002#[derive(
1003    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
1004)]
1005#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1006#[serde(rename_all = "snake_case")]
1007pub enum SyncCheckpoint {
1008    Genesis,
1009    EarliestAvailable,
1010}
1011
1012#[derive(
1013    Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, arbitrary::Arbitrary,
1014)]
1015#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1016#[serde(rename_all = "snake_case")]
1017pub enum BlockReference {
1018    BlockId(BlockId),
1019    Finality(Finality),
1020    SyncCheckpoint(SyncCheckpoint),
1021}
1022
1023impl BlockReference {
1024    pub fn latest() -> Self {
1025        Self::Finality(Finality::None)
1026    }
1027}
1028
1029impl From<BlockId> for BlockReference {
1030    fn from(block_id: BlockId) -> Self {
1031        Self::BlockId(block_id)
1032    }
1033}
1034
1035impl From<Finality> for BlockReference {
1036    fn from(finality: Finality) -> Self {
1037        Self::Finality(finality)
1038    }
1039}
1040
1041#[derive(
1042    Default,
1043    BorshSerialize,
1044    BorshDeserialize,
1045    Clone,
1046    Debug,
1047    PartialEq,
1048    Eq,
1049    ProtocolSchema,
1050    serde::Serialize,
1051)]
1052pub struct ValidatorStats {
1053    pub produced: NumBlocks,
1054    pub expected: NumBlocks,
1055}
1056
1057impl ValidatorStats {
1058    /// Compare stats with threshold which is an expected percentage from 0 to
1059    /// 100.
1060    pub fn less_than(&self, threshold: u8) -> bool {
1061        self.produced * 100 < u64::from(threshold) * self.expected
1062    }
1063}
1064
1065#[derive(Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq, ProtocolSchema)]
1066pub struct BlockChunkValidatorStats {
1067    pub block_stats: ValidatorStats,
1068    pub chunk_stats: ChunkStats,
1069}
1070
1071#[derive(serde::Deserialize, Debug, arbitrary::Arbitrary, PartialEq, Eq)]
1072#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1073#[serde(rename_all = "snake_case")]
1074pub enum EpochReference {
1075    EpochId(EpochId),
1076    BlockId(BlockId),
1077    Latest,
1078}
1079
1080impl serde::Serialize for EpochReference {
1081    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
1082    where
1083        S: serde::Serializer,
1084    {
1085        // cspell:words newtype
1086        match self {
1087            EpochReference::EpochId(epoch_id) => {
1088                s.serialize_newtype_variant("EpochReference", 0, "epoch_id", epoch_id)
1089            }
1090            EpochReference::BlockId(block_id) => {
1091                s.serialize_newtype_variant("EpochReference", 1, "block_id", block_id)
1092            }
1093            EpochReference::Latest => {
1094                s.serialize_newtype_variant("EpochReference", 2, "latest", &())
1095            }
1096        }
1097    }
1098}
1099
1100/// Either an epoch id or latest block hash.  When `EpochId` variant is used it
1101/// must be an identifier of a past epoch.  When `BlockHeight` is used it must
1102/// be hash of the latest block in the current epoch.  Using current epoch id
1103/// with `EpochId` or arbitrary block hash in past or present epochs will result
1104/// in errors.
1105#[derive(Clone, Debug)]
1106pub enum ValidatorInfoIdentifier {
1107    EpochId(EpochId),
1108    BlockHash(CryptoHash),
1109}
1110
1111/// Reasons for removing a validator from the validator set.
1112#[derive(
1113    BorshSerialize,
1114    BorshDeserialize,
1115    serde::Serialize,
1116    serde::Deserialize,
1117    Clone,
1118    Debug,
1119    PartialEq,
1120    Eq,
1121    ProtocolSchema,
1122)]
1123#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1124pub enum ValidatorKickoutReason {
1125    /// Deprecated
1126    _UnusedSlashed,
1127    /// Validator didn't produce enough blocks.
1128    NotEnoughBlocks { produced: NumBlocks, expected: NumBlocks },
1129    /// Validator didn't produce enough chunks.
1130    NotEnoughChunks { produced: NumBlocks, expected: NumBlocks },
1131    /// Validator unstaked themselves.
1132    Unstaked,
1133    /// Validator stake is now below threshold
1134    NotEnoughStake {
1135        #[serde(with = "dec_format", rename = "stake_u128")]
1136        #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1137        stake: Balance,
1138        #[serde(with = "dec_format", rename = "threshold_u128")]
1139        #[cfg_attr(feature = "schemars", schemars(with = "String"))]
1140        threshold: Balance,
1141    },
1142    /// Enough stake but is not chosen because of seat limits.
1143    DidNotGetASeat,
1144    /// Validator didn't produce enough chunk endorsements.
1145    NotEnoughChunkEndorsements { produced: NumBlocks, expected: NumBlocks },
1146    /// Validator's last block proposal was for a protocol version older than
1147    /// the network's voted protocol version.
1148    ProtocolVersionTooOld { version: ProtocolVersion, network_version: ProtocolVersion },
1149}
1150
1151#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
1152#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1153#[serde(tag = "type", rename_all = "snake_case")]
1154pub enum TransactionOrReceiptId {
1155    Transaction { transaction_hash: CryptoHash, sender_id: AccountId },
1156    Receipt { receipt_id: CryptoHash, receiver_id: AccountId },
1157}
1158
1159/// Provides information about current epoch validators.
1160/// Used to break dependency between epoch manager and runtime.
1161pub trait EpochInfoProvider: Send + Sync {
1162    /// Get current stake of a validator in the given epoch.
1163    /// If the account is not a validator, returns `None`.
1164    fn validator_stake(
1165        &self,
1166        epoch_id: &EpochId,
1167        account_id: &AccountId,
1168    ) -> Result<Option<Balance>, EpochError>;
1169
1170    /// Get the total stake of the given epoch.
1171    fn validator_total_stake(&self, epoch_id: &EpochId) -> Result<Balance, EpochError>;
1172
1173    fn minimum_stake(&self, prev_block_hash: &CryptoHash) -> Result<Balance, EpochError>;
1174
1175    /// Get the chain_id of the chain this epoch belongs to
1176    fn chain_id(&self) -> String;
1177
1178    fn shard_layout(&self, epoch_id: &EpochId) -> Result<ShardLayout, EpochError>;
1179}
1180
1181/// State changes for a range of blocks.
1182/// Expects that a block is present at most once in the list.
1183#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1184pub struct StateChangesForBlockRange {
1185    pub blocks: Vec<StateChangesForBlock>,
1186}
1187
1188/// State changes for a single block.
1189/// Expects that a shard is present at most once in the list of state changes.
1190#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1191pub struct StateChangesForBlock {
1192    pub block_hash: CryptoHash,
1193    pub state_changes: Vec<StateChangesForShard>,
1194}
1195
1196/// Key and value of a StateChanges column.
1197#[derive(borsh::BorshDeserialize, borsh::BorshSerialize)]
1198pub struct StateChangesForShard {
1199    pub shard_id: ShardId,
1200    pub state_changes: Vec<RawStateChangesWithTrieKey>,
1201}
1202
1203#[cfg(test)]
1204mod tests {
1205    use near_crypto::{KeyType, PublicKey};
1206    use near_primitives_core::types::Balance;
1207
1208    use super::validator_stake::ValidatorStake;
1209
1210    fn new_validator_stake(stake: Balance) -> ValidatorStake {
1211        ValidatorStake::new(
1212            "test_account".parse().unwrap(),
1213            PublicKey::empty(KeyType::ED25519),
1214            stake,
1215        )
1216    }
1217
1218    #[test]
1219    fn test_validator_stake_num_mandates() {
1220        assert_eq!(new_validator_stake(0).num_mandates(5), 0);
1221        assert_eq!(new_validator_stake(10).num_mandates(5), 2);
1222        assert_eq!(new_validator_stake(12).num_mandates(5), 2);
1223    }
1224
1225    #[test]
1226    fn test_validator_partial_mandate_weight() {
1227        assert_eq!(new_validator_stake(0).partial_mandate_weight(5), 0);
1228        assert_eq!(new_validator_stake(10).partial_mandate_weight(5), 0);
1229        assert_eq!(new_validator_stake(12).partial_mandate_weight(5), 2);
1230    }
1231}