mina_tree/proofs/
conv.rs

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