mina_tree/proofs/
conv.rs

1use ark_ff::fields::arithmetic::InvalidBigInt;
2use mina_curves::pasta::Fp;
3use mina_p2p_messages::v2;
4
5use crate::scan_state::{
6    currency::{self, Length, Slot},
7    transaction_logic::protocol_state::{EpochData, EpochLedger},
8};
9
10use super::{
11    block::{
12        consensus::{CheckedConsensusState, ConsensusState},
13        ProtocolState, ProtocolStateBody,
14    },
15    numbers::{
16        currency::{CheckedAmount, CheckedCurrency},
17        nat::{CheckedLength, CheckedNat, CheckedSlot},
18    },
19};
20
21fn state_hash(value: Fp) -> v2::StateHash {
22    v2::DataHashLibStateHashStableV1(value.into()).into()
23}
24
25fn ledger_hash(value: Fp) -> v2::LedgerHash {
26    v2::MinaBaseLedgerHash0StableV1(value.into()).into()
27}
28
29fn epoch_ledger_seed(value: Fp) -> v2::EpochSeed {
30    v2::MinaBaseEpochSeedStableV1(value.into()).into()
31}
32
33impl From<CheckedLength<Fp>> for v2::UnsignedExtendedUInt32StableV1 {
34    fn from(value: CheckedLength<Fp>) -> Self {
35        Self(value.to_inner().as_u32().into())
36    }
37}
38
39impl From<CheckedSlot<Fp>> for v2::UnsignedExtendedUInt32StableV1 {
40    fn from(value: CheckedSlot<Fp>) -> Self {
41        Self(value.to_inner().as_u32().into())
42    }
43}
44
45impl From<CheckedAmount<Fp>> for v2::UnsignedExtendedUInt64Int64ForVersionTagsStableV1 {
46    fn from(value: CheckedAmount<Fp>) -> Self {
47        Self(value.to_inner().as_u64().into())
48    }
49}
50
51impl From<CheckedAmount<Fp>> for v2::CurrencyAmountStableV1 {
52    fn from(value: CheckedAmount<Fp>) -> Self {
53        Self(value.into())
54    }
55}
56
57impl From<&EpochLedger<Fp>> for v2::MinaBaseEpochLedgerValueStableV1 {
58    fn from(value: &EpochLedger<Fp>) -> Self {
59        Self {
60            hash: ledger_hash(value.hash),
61            total_currency: value.total_currency.into(),
62        }
63    }
64}
65
66impl From<&EpochData<Fp>>
67    for v2::ConsensusProofOfStakeDataEpochDataStakingValueVersionedValueStableV1
68{
69    fn from(value: &EpochData<Fp>) -> Self {
70        Self {
71            ledger: (&value.ledger).into(),
72            seed: epoch_ledger_seed(value.seed),
73            start_checkpoint: state_hash(value.start_checkpoint),
74            lock_checkpoint: state_hash(value.lock_checkpoint),
75            epoch_length: (&value.epoch_length).into(),
76        }
77    }
78}
79
80impl From<&EpochData<Fp>>
81    for v2::ConsensusProofOfStakeDataEpochDataNextValueVersionedValueStableV1
82{
83    fn from(value: &EpochData<Fp>) -> Self {
84        Self {
85            ledger: (&value.ledger).into(),
86            seed: epoch_ledger_seed(value.seed),
87            start_checkpoint: state_hash(value.start_checkpoint),
88            lock_checkpoint: state_hash(value.lock_checkpoint),
89            epoch_length: (&value.epoch_length).into(),
90        }
91    }
92}
93
94impl From<&ProtocolState> for v2::MinaStateProtocolStateValueStableV2 {
95    fn from(value: &ProtocolState) -> Self {
96        Self {
97            previous_state_hash: state_hash(value.previous_state_hash),
98            body: (&value.body).into(),
99        }
100    }
101}
102
103impl TryFrom<&v2::MinaStateProtocolStateValueStableV2> for ProtocolState {
104    type Error = InvalidBigInt;
105
106    fn try_from(value: &v2::MinaStateProtocolStateValueStableV2) -> Result<Self, Self::Error> {
107        let v2::MinaStateProtocolStateValueStableV2 {
108            previous_state_hash,
109            body,
110        } = value;
111
112        Ok(Self {
113            previous_state_hash: previous_state_hash.to_field()?,
114            body: body.try_into()?,
115        })
116    }
117}
118
119impl From<&super::block::BlockchainState> for v2::MinaStateBlockchainStateValueStableV2 {
120    fn from(value: &super::block::BlockchainState) -> Self {
121        let super::block::BlockchainState {
122            staged_ledger_hash,
123            genesis_ledger_hash,
124            ledger_proof_statement,
125            timestamp,
126            body_reference,
127        } = value;
128
129        Self {
130            staged_ledger_hash: staged_ledger_hash.into(),
131            genesis_ledger_hash: genesis_ledger_hash.into(),
132            ledger_proof_statement: ledger_proof_statement.into(),
133            timestamp: timestamp.into(),
134            body_reference: body_reference.clone(),
135        }
136    }
137}
138
139impl From<&ProtocolStateBody<ConsensusState>> for v2::MinaStateProtocolStateBodyValueStableV2 {
140    fn from(value: &ProtocolStateBody) -> Self {
141        Self {
142            genesis_state_hash: state_hash(value.genesis_state_hash),
143            blockchain_state: (&value.blockchain_state).into(),
144            consensus_state: (&value.consensus_state).into(),
145            constants: value.constants.clone(),
146        }
147    }
148}
149
150impl TryFrom<&v2::MinaStateProtocolStateBodyValueStableV2> for ProtocolStateBody<ConsensusState> {
151    type Error = InvalidBigInt;
152
153    fn try_from(value: &v2::MinaStateProtocolStateBodyValueStableV2) -> Result<Self, Self::Error> {
154        let v2::MinaStateProtocolStateBodyValueStableV2 {
155            genesis_state_hash,
156            blockchain_state,
157            consensus_state,
158            constants,
159        } = value;
160
161        Ok(Self {
162            genesis_state_hash: genesis_state_hash.to_field()?,
163            blockchain_state: blockchain_state.try_into()?,
164            consensus_state: consensus_state.try_into()?,
165            constants: constants.clone(),
166        })
167    }
168}
169
170impl TryFrom<&v2::ConsensusProofOfStakeDataConsensusStateValueStableV2> for ConsensusState {
171    type Error = InvalidBigInt;
172
173    fn try_from(
174        value: &v2::ConsensusProofOfStakeDataConsensusStateValueStableV2,
175    ) -> Result<Self, Self::Error> {
176        let v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
177            blockchain_length,
178            epoch_count,
179            min_window_density,
180            sub_window_densities,
181            last_vrf_output,
182            total_currency,
183            curr_global_slot_since_hard_fork,
184            global_slot_since_genesis,
185            staking_epoch_data,
186            next_epoch_data,
187            has_ancestor_in_same_checkpoint_window,
188            block_stake_winner,
189            block_creator,
190            coinbase_receiver,
191            supercharge_coinbase,
192        } = value;
193
194        Ok(Self {
195            blockchain_length: Length::from_u32(blockchain_length.as_u32()),
196            epoch_count: Length::from_u32(epoch_count.as_u32()),
197            min_window_density: Length::from_u32(min_window_density.as_u32()),
198            sub_window_densities: sub_window_densities
199                .iter()
200                .map(|sub| Length::from_u32(sub.as_u32()))
201                .collect(),
202            last_vrf_output: {
203                let mut output = Vec::with_capacity(253);
204                output.extend(last_vrf_output.iter().take(31).flat_map(|b| {
205                    [1u8, 2, 4, 8, 16, 32, 64, 128]
206                        .iter()
207                        .map(|bit| *bit & *b != 0)
208                }));
209                // Ignore last 3 bits
210                let last_byte = last_vrf_output[31];
211                output.extend([1, 2, 4, 8, 16].iter().map(|bit| *bit & last_byte != 0));
212                output.try_into().map_err(|_| InvalidBigInt)? // TODO: Return correct error
213            },
214            curr_global_slot_since_hard_fork: curr_global_slot_since_hard_fork.into(),
215            global_slot_since_genesis: Slot::from_u32(global_slot_since_genesis.as_u32()),
216            total_currency: currency::Amount::from_u64(total_currency.as_u64()),
217            staking_epoch_data: staking_epoch_data.try_into()?,
218            next_epoch_data: next_epoch_data.try_into()?,
219            has_ancestor_in_same_checkpoint_window: *has_ancestor_in_same_checkpoint_window,
220            block_stake_winner: block_stake_winner.try_into()?,
221            block_creator: block_creator.try_into()?,
222            coinbase_receiver: coinbase_receiver.try_into()?,
223            supercharge_coinbase: *supercharge_coinbase,
224        })
225    }
226}
227
228impl From<&CheckedConsensusState> for v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
229    fn from(value: &CheckedConsensusState) -> Self {
230        Self {
231            blockchain_length: value.blockchain_length.into(),
232            epoch_count: value.epoch_count.into(),
233            min_window_density: value.min_window_density.into(),
234            sub_window_densities: value
235                .sub_window_densities
236                .iter()
237                .map(|v| (*v).into())
238                .collect(),
239            // can't restore it.
240            last_vrf_output: v2::ConsensusVrfOutputTruncatedStableV1(Vec::new().into()),
241            total_currency: value.total_currency.into(),
242            curr_global_slot_since_hard_fork: v2::ConsensusGlobalSlotStableV1 {
243                slot_number: v2::MinaNumbersGlobalSlotSinceHardForkMStableV1::SinceHardFork(
244                    value.curr_global_slot_since_hard_fork.slot_number.into(),
245                ),
246                slots_per_epoch: value
247                    .curr_global_slot_since_hard_fork
248                    .slots_per_epoch
249                    .into(),
250            },
251            global_slot_since_genesis: v2::MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
252                v2::UnsignedExtendedUInt32StableV1(
253                    value.global_slot_since_genesis.to_inner().as_u32().into(),
254                ),
255            ),
256            staking_epoch_data: (&value.staking_epoch_data).into(),
257            next_epoch_data: (&value.next_epoch_data).into(),
258            has_ancestor_in_same_checkpoint_window: value
259                .has_ancestor_in_same_checkpoint_window
260                .as_bool(),
261            block_stake_winner: (&value.block_stake_winner).into(),
262            block_creator: (&value.block_creator).into(),
263            coinbase_receiver: (&value.coinbase_receiver).into(),
264            supercharge_coinbase: value.supercharge_coinbase.as_bool(),
265        }
266    }
267}
268
269impl From<&ConsensusState> for v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
270    fn from(value: &ConsensusState) -> Self {
271        Self {
272            blockchain_length: value.blockchain_length.as_u32().into(),
273            epoch_count: value.epoch_count.as_u32().into(),
274            min_window_density: value.min_window_density.as_u32().into(),
275            sub_window_densities: value
276                .sub_window_densities
277                .iter()
278                .map(|v| v.as_u32().into())
279                .collect(),
280            // can't restore it.
281            last_vrf_output: v2::ConsensusVrfOutputTruncatedStableV1(Vec::new().into()),
282            total_currency: value.total_currency.into(),
283            curr_global_slot_since_hard_fork: v2::ConsensusGlobalSlotStableV1 {
284                slot_number: v2::MinaNumbersGlobalSlotSinceHardForkMStableV1::SinceHardFork(
285                    value.curr_global_slot_since_hard_fork.slot_number.into(),
286                ),
287                slots_per_epoch: value
288                    .curr_global_slot_since_hard_fork
289                    .slots_per_epoch
290                    .into(),
291            },
292            global_slot_since_genesis: v2::MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
293                v2::UnsignedExtendedUInt32StableV1(value.global_slot_since_genesis.as_u32().into()),
294            ),
295            staking_epoch_data: (&value.staking_epoch_data).into(),
296            next_epoch_data: (&value.next_epoch_data).into(),
297            has_ancestor_in_same_checkpoint_window: value.has_ancestor_in_same_checkpoint_window,
298            block_stake_winner: (&value.block_stake_winner).into(),
299            block_creator: (&value.block_creator).into(),
300            coinbase_receiver: (&value.coinbase_receiver).into(),
301            supercharge_coinbase: value.supercharge_coinbase,
302        }
303    }
304}