mina_tree/scan_state/transaction_logic/
protocol_state.rs

1use crate::{
2    proofs::field::FieldWitness,
3    scan_state::currency::{Amount, Length, Signed, Slot},
4    sparse_ledger::LedgerIntf,
5};
6use mina_curves::pasta::Fp;
7use mina_p2p_messages::{
8    bigint::InvalidBigInt,
9    v2::{self, MinaStateProtocolStateValueStableV2},
10};
11
12#[derive(Debug, Clone)]
13pub struct EpochLedger<F: FieldWitness> {
14    pub hash: F,
15    pub total_currency: Amount,
16}
17
18#[derive(Debug, Clone)]
19pub struct EpochData<F: FieldWitness> {
20    pub ledger: EpochLedger<F>,
21    pub seed: F,
22    pub start_checkpoint: F,
23    pub lock_checkpoint: F,
24    pub epoch_length: Length,
25}
26
27#[derive(Debug, Clone)]
28pub struct ProtocolStateView {
29    pub snarked_ledger_hash: Fp,
30    pub blockchain_length: Length,
31    pub min_window_density: Length,
32    pub total_currency: Amount,
33    pub global_slot_since_genesis: Slot,
34    pub staking_epoch_data: EpochData<Fp>,
35    pub next_epoch_data: EpochData<Fp>,
36}
37
38/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/mina_state/protocol_state.ml#L180>
39pub fn protocol_state_view(
40    state: &MinaStateProtocolStateValueStableV2,
41) -> Result<ProtocolStateView, InvalidBigInt> {
42    let MinaStateProtocolStateValueStableV2 {
43        previous_state_hash: _,
44        body,
45    } = state;
46
47    protocol_state_body_view(body)
48}
49
50pub fn protocol_state_body_view(
51    body: &v2::MinaStateProtocolStateBodyValueStableV2,
52) -> Result<ProtocolStateView, InvalidBigInt> {
53    let cs = &body.consensus_state;
54    let sed = &cs.staking_epoch_data;
55    let ned = &cs.next_epoch_data;
56
57    Ok(ProtocolStateView {
58        // <https://github.com/MinaProtocol/mina/blob/436023ba41c43a50458a551b7ef7a9ae61670b25/src/lib/mina_state/blockchain_state.ml#L58>
59        //
60        snarked_ledger_hash: body
61            .blockchain_state
62            .ledger_proof_statement
63            .target
64            .first_pass_ledger
65            .to_field()?,
66        blockchain_length: Length(cs.blockchain_length.as_u32()),
67        min_window_density: Length(cs.min_window_density.as_u32()),
68        total_currency: Amount(cs.total_currency.as_u64()),
69        global_slot_since_genesis: (&cs.global_slot_since_genesis).into(),
70        staking_epoch_data: EpochData {
71            ledger: EpochLedger {
72                hash: sed.ledger.hash.to_field()?,
73                total_currency: Amount(sed.ledger.total_currency.as_u64()),
74            },
75            seed: sed.seed.to_field()?,
76            start_checkpoint: sed.start_checkpoint.to_field()?,
77            lock_checkpoint: sed.lock_checkpoint.to_field()?,
78            epoch_length: Length(sed.epoch_length.as_u32()),
79        },
80        next_epoch_data: EpochData {
81            ledger: EpochLedger {
82                hash: ned.ledger.hash.to_field()?,
83                total_currency: Amount(ned.ledger.total_currency.as_u64()),
84            },
85            seed: ned.seed.to_field()?,
86            start_checkpoint: ned.start_checkpoint.to_field()?,
87            lock_checkpoint: ned.lock_checkpoint.to_field()?,
88            epoch_length: Length(ned.epoch_length.as_u32()),
89        },
90    })
91}
92
93pub type GlobalState<L> = GlobalStateSkeleton<L, Signed<Amount>, Slot>;
94
95#[derive(Debug, Clone)]
96pub struct GlobalStateSkeleton<L, SignedAmount, Slot> {
97    pub first_pass_ledger: L,
98    pub second_pass_ledger: L,
99    pub fee_excess: SignedAmount,
100    pub supply_increase: SignedAmount,
101    pub protocol_state: ProtocolStateView,
102    /// Slot of block when the transaction is applied.
103    /// NOTE: This is at least 1 slot after the protocol_state's view,
104    /// which is for the *previous* slot.
105    pub block_global_slot: Slot,
106}
107
108impl<L: LedgerIntf + Clone> GlobalState<L> {
109    pub fn first_pass_ledger(&self) -> L {
110        self.first_pass_ledger.create_masked()
111    }
112
113    #[must_use]
114    pub fn set_first_pass_ledger(&self, should_update: bool, ledger: L) -> Self {
115        let mut this = self.clone();
116        if should_update {
117            this.first_pass_ledger.apply_mask(ledger);
118        }
119        this
120    }
121
122    pub fn second_pass_ledger(&self) -> L {
123        self.second_pass_ledger.create_masked()
124    }
125
126    #[must_use]
127    pub fn set_second_pass_ledger(&self, should_update: bool, ledger: L) -> Self {
128        let mut this = self.clone();
129        if should_update {
130            this.second_pass_ledger.apply_mask(ledger);
131        }
132        this
133    }
134
135    pub fn fee_excess(&self) -> Signed<Amount> {
136        self.fee_excess
137    }
138
139    #[must_use]
140    pub fn set_fee_excess(&self, fee_excess: Signed<Amount>) -> Self {
141        let mut this = self.clone();
142        this.fee_excess = fee_excess;
143        this
144    }
145
146    pub fn supply_increase(&self) -> Signed<Amount> {
147        self.supply_increase
148    }
149
150    #[must_use]
151    pub fn set_supply_increase(&self, supply_increase: Signed<Amount>) -> Self {
152        let mut this = self.clone();
153        this.supply_increase = supply_increase;
154        this
155    }
156
157    pub fn block_global_slot(&self) -> Slot {
158        self.block_global_slot
159    }
160}