1pub mod conv;
2use crate::{
3 b58::{self, Base58CheckOfBinProt, Base58CheckOfBytes},
4 b58version::USER_COMMAND_MEMO,
5 bigint::BigInt,
6 list::List,
7 number::Number,
8 string::ByteString,
9 versioned::Versioned,
10};
11use ark_ff::BigInteger256;
12use binprot::{BinProtRead, BinProtWrite};
13use binprot_derive::{BinProtRead, BinProtWrite};
14use derive_more::Deref;
15use malloc_size_of_derive::MallocSizeOf;
16use poseidon::hash::params::NO_INPUT_COINBASE_STACK;
17use serde::{de::Visitor, ser::SerializeTuple, Deserialize, Serialize, Serializer};
18use time::OffsetDateTime;
19
20use super::*;
21
22pub type TransactionSnarkScanStateStableV2TreesABase = (
23 ParallelScanWeightStableV1,
24 TransactionSnarkScanStateStableV2ScanStateTreesABaseT1,
25);
26
27pub type TransactionSnarkScanStateStableV2TreesAMerge = (
28 (ParallelScanWeightStableV1, ParallelScanWeightStableV1),
29 TransactionSnarkScanStateStableV2ScanStateTreesAMergeT1,
30);
31
32#[derive(Clone, Debug, PartialEq, BinProtRead, BinProtWrite, Deref, MallocSizeOf)]
45pub struct MinaBaseSignedCommandMemoStableV1(pub crate::string::CharString);
46
47impl MinaBaseSignedCommandMemoStableV1 {
48 pub fn to_base58check(&self) -> String {
49 b58::encode(self.0.as_ref(), USER_COMMAND_MEMO)
50 }
51
52 pub fn from_base58check(s: &str) -> Self {
53 let decoded = b58::decode(s, USER_COMMAND_MEMO).unwrap();
54 MinaBaseSignedCommandMemoStableV1(decoded[1..].into())
55 }
56}
57
58impl Serialize for MinaBaseSignedCommandMemoStableV1 {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: serde::ser::Serializer,
62 {
63 if serializer.is_human_readable() {
64 let base58check = b58::encode(self.0.as_ref(), USER_COMMAND_MEMO);
65 base58check.serialize(serializer)
66 } else {
67 self.0.serialize(serializer)
68 }
69 }
70}
71
72impl<'de> Deserialize<'de> for MinaBaseSignedCommandMemoStableV1 {
73 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
74 where
75 D: serde::de::Deserializer<'de>,
76 {
77 if deserializer.is_human_readable() {
78 let base58check = String::deserialize(deserializer)?;
79 let decoded = b58::decode(&base58check, USER_COMMAND_MEMO)
80 .map_err(|err| serde::de::Error::custom(format!("Base58 decode error: {}", err)))?;
81 Ok(MinaBaseSignedCommandMemoStableV1(decoded[1..].into()))
82 } else {
83 let char_string = crate::string::CharString::deserialize(deserializer)?;
84 Ok(MinaBaseSignedCommandMemoStableV1(char_string))
85 }
86 }
87}
88
89#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
94pub enum TransactionSnarkScanStateStableV2ScanStateTreesA {
95 Leaf(Vec<TransactionSnarkScanStateStableV2TreesABase>),
96 Node {
97 depth: crate::number::Int32,
98 value: Vec<TransactionSnarkScanStateStableV2TreesAMerge>,
99 sub_tree: Box<TransactionSnarkScanStateStableV2ScanStateTreesA>,
100 },
101}
102
103#[derive(BinProtRead, BinProtWrite)]
104enum _Tree {
105 Leaf,
106 Node,
107}
108
109impl BinProtRead for TransactionSnarkScanStateStableV2ScanStateTreesA {
110 fn binprot_read<R: std::io::Read + ?Sized>(r: &mut R) -> Result<Self, binprot::Error>
111 where
112 Self: Sized,
113 {
114 let mut depth: i32 = 0;
115 let mut values: Vec<Vec<TransactionSnarkScanStateStableV2TreesAMerge>> = Vec::new();
116 loop {
117 match _Tree::binprot_read(r)? {
118 _Tree::Leaf => {
119 let len = 1 << depth;
120 let mut data = Vec::with_capacity(len);
121 for _ in 0..len {
122 data.push(TransactionSnarkScanStateStableV2TreesABase::binprot_read(
123 r,
124 )?)
125 }
126 let mut tree = Self::Leaf(data);
127 while let Some(value) = values.pop() {
128 depth = depth - 1;
129 tree = Self::Node {
130 depth: depth.into(),
131 value,
132 sub_tree: Box::new(tree),
133 }
134 }
135 return Ok(tree);
136 }
137 _Tree::Node => {
138 let _depth = i32::binprot_read(r)?;
139 if _depth != depth {
140 return Err(binprot::Error::CustomError(
141 format!("Incorrect tree depth, expected `{depth}`, got `{_depth}`")
142 .into(),
143 ));
144 }
145 let len = 1 << depth;
146 let mut value = Vec::with_capacity(len);
147 for _ in 0..len {
148 value.push(TransactionSnarkScanStateStableV2TreesAMerge::binprot_read(
149 r,
150 )?)
151 }
152 values.push(value);
153 depth += 1;
154 }
155 }
156 }
157 }
158}
159
160impl BinProtWrite for TransactionSnarkScanStateStableV2ScanStateTreesA {
161 fn binprot_write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
162 let mut curr = self;
163 let mut curr_depth = 0;
164 loop {
165 match curr {
166 Self::Leaf(leaf) => {
167 let len = 1 << curr_depth;
168 if leaf.len() != len {
169 return Err(std::io::Error::new(
170 std::io::ErrorKind::InvalidInput,
171 format!(
172 "Invalid leaf data lenght, expecting {len}, got {}",
173 leaf.len()
174 ),
175 ));
176 }
177 _Tree::Leaf.binprot_write(w)?;
178 leaf.iter().try_for_each(|b| b.binprot_write(w))?;
179 return Ok(());
180 }
181 Self::Node {
182 depth,
183 value,
184 sub_tree,
185 } => {
186 if &depth.0 != &curr_depth {
187 return Err(std::io::Error::new(
188 std::io::ErrorKind::InvalidInput,
189 format!(
190 "Invalid depth, expecting {curr_depth}, got {depth}",
191 depth = depth.0
192 ),
193 ));
194 }
195 if value.len() != (1 << curr_depth) {
196 return Err(std::io::Error::new(
197 std::io::ErrorKind::InvalidInput,
198 format!(
199 "Invalid node data lenght, expecting {}, got {}",
200 1 << curr_depth,
201 value.len()
202 ),
203 ));
204 }
205 _Tree::Node.binprot_write(w)?;
206 depth.binprot_write(w)?;
207 value.iter().try_for_each(|b| b.binprot_write(w))?;
208 curr = sub_tree;
209 curr_depth += 1;
210 }
211 }
212 }
213 }
214}
215
216impl rsexp::OfSexp for PicklesBaseProofsVerifiedStableV1 {
220 fn of_sexp(s: &rsexp::Sexp) -> Result<Self, rsexp::IntoSexpError>
221 where
222 Self: Sized,
223 {
224 match s.extract_enum("PicklesBaseProofsVerifiedStableV1")? {
225 (b"N0", _) => Ok(PicklesBaseProofsVerifiedStableV1::N0),
226 (b"N1", _) => Ok(PicklesBaseProofsVerifiedStableV1::N1),
227 (b"N2", _) => Ok(PicklesBaseProofsVerifiedStableV1::N2),
228 (ctor, _) => Err(rsexp::IntoSexpError::UnknownConstructorForEnum {
229 type_: "PicklesBaseProofsVerifiedStableV1",
230 constructor: String::from_utf8_lossy(ctor).to_string(),
231 }),
232 }
233 }
234}
235
236impl rsexp::OfSexp for LimbVectorConstantHex64StableV1 {
237 fn of_sexp(s: &rsexp::Sexp) -> Result<Self, rsexp::IntoSexpError>
238 where
239 Self: Sized,
240 {
241 let bytes = s.extract_atom("LimbVectorConstantHex64StableV1")?;
242 let hex_str = std::str::from_utf8(bytes).map_err(|_| {
243 rsexp::IntoSexpError::StringConversionError {
244 err: format!("Expected 16 bytes hex string, got {bytes:?}"),
245 }
246 })?;
247 if hex_str.len() != 16 {
248 return Err(rsexp::IntoSexpError::StringConversionError {
249 err: format!("Expected 16 bytes hex string, got {hex_str:?}"),
250 });
251 }
252 let n = u64::from_str_radix(hex_str, 16).map_err(|_| {
253 rsexp::IntoSexpError::StringConversionError {
254 err: format!("Expected 16 bytes hex string, got {hex_str:?}"),
255 }
256 })?;
257
258 Ok(Self(n.into()))
259 }
260}
261
262impl rsexp::SexpOf for LimbVectorConstantHex64StableV1 {
263 fn sexp_of(&self) -> rsexp::Sexp {
264 let value: u64 = self.0.as_u64();
265 let hex_str = format!("{:016x}", value);
266
267 rsexp::Sexp::Atom(format!("0x{}", hex_str).into_bytes())
268 }
269}
270
271impl rsexp::OfSexp for CompositionTypesBranchDataDomainLog2StableV1 {
272 fn of_sexp(s: &rsexp::Sexp) -> Result<Self, rsexp::IntoSexpError>
273 where
274 Self: Sized,
275 {
276 match s.extract_atom("CompositionTypesBranchDataDomainLog2StableV1")? {
277 [ch] => Ok(Self((*ch).into())),
278 bytes => Err(rsexp::IntoSexpError::StringConversionError {
279 err: format!("Expected single byte string, got {bytes:?}"),
280 }),
281 }
282 }
283}
284
285impl rsexp::SexpOf for CompositionTypesBranchDataDomainLog2StableV1 {
286 fn sexp_of(&self) -> rsexp::Sexp {
287 rsexp::Sexp::Atom(vec![self.0.as_u8()])
288 }
289}
290
291impl rsexp::OfSexp for CompositionTypesDigestConstantStableV1 {
292 fn of_sexp(s: &rsexp::Sexp) -> std::result::Result<Self, rsexp::IntoSexpError> {
293 Ok(Self(crate::pseq::PaddedSeq::<
294 LimbVectorConstantHex64StableV1,
295 4,
296 >::of_sexp(s)?))
297 }
298}
299
300impl rsexp::SexpOf for CompositionTypesDigestConstantStableV1 {
301 fn sexp_of(&self) -> rsexp::Sexp {
302 self.0.sexp_of()
303 }
304}
305
306impl rsexp::OfSexp for PicklesReducedMessagesForNextProofOverSameFieldWrapChallengesVectorStableV2 {
307 fn of_sexp(s: &rsexp::Sexp) -> std::result::Result<Self, rsexp::IntoSexpError> {
308 Ok(Self(crate::pseq::PaddedSeq::<
309 PicklesReducedMessagesForNextProofOverSameFieldWrapChallengesVectorStableV2A,
310 15,
311 >::of_sexp(s)?))
312 }
313}
314
315impl rsexp::SexpOf for PicklesReducedMessagesForNextProofOverSameFieldWrapChallengesVectorStableV2 {
316 fn sexp_of(&self) -> rsexp::Sexp {
317 self.0.sexp_of()
318 }
319}
320
321impl rsexp::OfSexp for TransactionSnarkProofStableV2 {
322 fn of_sexp(s: &rsexp::Sexp) -> std::result::Result<Self, rsexp::IntoSexpError> {
323 Ok(Self(PicklesProofProofsVerified2ReprStableV2::of_sexp(s)?))
324 }
325}
326
327impl rsexp::SexpOf for TransactionSnarkProofStableV2 {
328 fn sexp_of(&self) -> rsexp::Sexp {
329 self.0.sexp_of()
330 }
331}
332
333impl serde::Serialize for TransactionSnarkProofStableV2 {
334 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
335 where
336 S: serde::Serializer,
337 {
338 if serializer.is_human_readable() {
339 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
340 use rsexp::SexpOf;
341
342 let sexp = self.sexp_of();
343 let sexp_bytes = sexp.to_bytes();
344 let base64_data = URL_SAFE.encode(&sexp_bytes);
345
346 base64_data.serialize(serializer)
347 } else {
348 serializer.serialize_newtype_struct("TransactionSnarkProofStableV2", &self.0)
349 }
350 }
351}
352
353impl<'de> Deserialize<'de> for TransactionSnarkProofStableV2 {
354 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
355 where
356 D: serde::de::Deserializer<'de>,
357 {
358 if deserializer.is_human_readable() {
359 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
360 use rsexp::OfSexp;
361 let base64_data = String::deserialize(deserializer)?;
362 let sexp_data = URL_SAFE
363 .decode(&base64_data)
364 .map_err(serde::de::Error::custom)?;
365 let sexp = rsexp::from_slice(&sexp_data).map_err(|err| {
366 serde::de::Error::custom(format!("S-exp parsing failure: {err:?}"))
367 })?;
368 let proof = Self::of_sexp(&sexp).map_err(serde::de::Error::custom)?;
369 Ok(proof)
370 } else {
371 struct TransactionSnarkProofStableV2Visitor;
372
373 impl<'de> serde::de::Visitor<'de> for TransactionSnarkProofStableV2Visitor {
374 type Value = TransactionSnarkProofStableV2;
375
376 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
377 formatter.write_str("a valid TransactionSnarkProofStableV2")
378 }
379
380 fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
381 where
382 D: serde::de::Deserializer<'de>,
383 {
384 let inner_value =
385 PicklesProofProofsVerified2ReprStableV2::deserialize(deserializer)?;
386 Ok(TransactionSnarkProofStableV2(inner_value))
387 }
388 }
389
390 deserializer.deserialize_newtype_struct(
391 "TransactionSnarkProofStableV2",
392 TransactionSnarkProofStableV2Visitor,
393 )
394 }
395 }
396}
397
398impl<'de> Deserialize<'de> for PicklesProofProofsVerifiedMaxStableV2 {
399 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
400 where
401 D: serde::de::Deserializer<'de>,
402 {
403 if deserializer.is_human_readable() {
404 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
405 use rsexp::OfSexp;
406 let base64_data = String::deserialize(deserializer)?;
407 let sexp_data = URL_SAFE
408 .decode(&base64_data)
409 .map_err(serde::de::Error::custom)?;
410 let sexp = rsexp::from_slice(&sexp_data).map_err(|err| {
411 serde::de::Error::custom(format!("S-exp parsing failure: {err:?}"))
412 })?;
413 let proof = Self::of_sexp(&sexp).map_err(serde::de::Error::custom)?;
414 Ok(proof)
415 } else {
416 #[derive(Deserialize)]
417 struct Inner {
418 statement: PicklesProofProofsVerified2ReprStableV2Statement,
419 prev_evals: PicklesProofProofsVerified2ReprStableV2PrevEvals,
420 proof: PicklesWrapWireProofStableV1,
421 }
422
423 let inner = Inner::deserialize(deserializer)?;
424 Ok(PicklesProofProofsVerifiedMaxStableV2 {
425 statement: inner.statement,
426 prev_evals: inner.prev_evals,
427 proof: inner.proof,
428 })
429 }
430 }
431}
432
433impl serde::Serialize for PicklesProofProofsVerifiedMaxStableV2 {
434 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
435 where
436 S: serde::Serializer,
437 {
438 if serializer.is_human_readable() {
439 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
440 use rsexp::SexpOf as _;
441
442 let sexp = self.sexp_of();
443 let sexp_bytes = sexp.to_bytes();
444 let base64_data = URL_SAFE.encode(&sexp_bytes);
445
446 base64_data.serialize(serializer)
447 } else {
448 use serde::ser::SerializeStruct;
449 let mut state =
450 serializer.serialize_struct("PicklesProofProofsVerifiedMaxStableV2", 3)?;
451 state.serialize_field("statement", &self.statement)?;
452 state.serialize_field("prev_evals", &self.prev_evals)?;
453 state.serialize_field("proof", &self.proof)?;
454 state.end()
455 }
456 }
457}
458
459macro_rules! base58check_openapi_impl {
460 ($name:ident) => {
461 #[cfg(feature = "openapi")]
462 const _: () = {
463 use utoipa::openapi::schema::{Object, SchemaType, Type};
464 impl utoipa::PartialSchema for $name {
465 fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
466 Object::builder()
467 .schema_type(SchemaType::Type(Type::String))
468 .description(Some("Base58check-encoded data"))
469 .pattern(Some("^[1-9A-HJ-NP-Za-km-z]+$"))
470 .build()
471 .into()
472 }
473 }
474 impl utoipa::ToSchema for $name {
475 fn name() -> std::borrow::Cow<'static, str> {
476 std::borrow::Cow::Borrowed(stringify!($name))
477 }
478 }
479 };
480 };
481}
482
483base58check_openapi_impl!(MinaBaseSignedCommandMemoStableV1);
484
485macro_rules! base58check_of_binprot {
486 ($name:ident, versioned($ty:ty, $version:expr), $version_byte:ident) => {
487 impl From<Versioned<$ty, $version>> for $ty {
488 fn from(source: Versioned<$ty, $version>) -> Self {
489 source.into_inner()
490 }
491 }
492
493 pub type $name = Base58CheckOfBinProt<
494 $ty,
495 Versioned<$ty, $version>,
496 { $crate::b58version::$version_byte },
497 >;
498
499 base58check_openapi_impl!($name);
500 };
501 ($name:ident, versioned $ty:ty, $version_byte:ident) => {
502 base58check_of_binprot!($name, versioned($ty, 1), $version_byte);
503 };
504 ($name:ident, $ty:ty, $version_byte:ident) => {
505 pub type $name = Base58CheckOfBinProt<$ty, $ty, { $crate::b58version::$version_byte }>;
506 base58check_openapi_impl!($name);
507 };
508}
509
510macro_rules! base58check_of_bytes {
511 ($name:ident, $ty:ty, $version_byte:ident) => {
512 pub type $name = Base58CheckOfBytes<$ty, { $crate::b58version::$version_byte }>;
513 base58check_openapi_impl!($name);
514 };
515}
516
517base58check_of_binprot!(LedgerHash, versioned MinaBaseLedgerHash0StableV1, LEDGER_HASH);
518base58check_of_bytes!(
519 StagedLedgerHashAuxHash,
520 crate::string::ByteString,
521 STAGED_LEDGER_HASH_AUX_HASH
522);
523base58check_of_binprot!(EpochSeed, versioned MinaBaseEpochSeedStableV1, EPOCH_SEED);
524base58check_of_bytes!(
525 StagedLedgerHashPendingCoinbaseAux,
526 crate::string::ByteString,
527 STAGED_LEDGER_HASH_PENDING_COINBASE_AUX
528);
529base58check_of_binprot!(StateHash, versioned DataHashLibStateHashStableV1, STATE_HASH);
530base58check_of_binprot!(StateBodyHash, versioned MinaBaseStateBodyHashStableV1, STATE_BODY_HASH);
531base58check_of_binprot!(
532 PendingCoinbaseHash,
533 versioned MinaBasePendingCoinbaseHashVersionedStableV1,
534 RECEIPT_CHAIN_HASH
535);
536base58check_of_binprot!(
537 ReceiptChainHash,
538 versioned MinaBaseReceiptChainHashStableV1,
539 RECEIPT_CHAIN_HASH
540);
541base58check_of_binprot!(
542 TokenIdKeyHash,
543 MinaBaseAccountIdDigestStableV1,
544 TOKEN_ID_KEY
545);
546base58check_of_binprot!(
547 CoinbaseStackData,
548 versioned MinaBasePendingCoinbaseCoinbaseStackStableV1,
549 COINBASE_STACK_DATA
550);
551base58check_of_binprot!(
552 CoinbaseStackHash,
553 versioned MinaBasePendingCoinbaseStackHashStableV1,
554 COINBASE_STACK_HASH
555);
556base58check_of_binprot!(
557 Signature,
558 versioned MinaBaseSignatureStableV1,
559 SIGNATURE
560);
561
562impl StateHash {
563 pub fn zero() -> Self {
564 DataHashLibStateHashStableV1(BigInt::zero()).into()
565 }
566}
567
568impl EpochSeed {
569 pub fn zero() -> Self {
570 MinaBaseEpochSeedStableV1(BigInt::zero()).into()
571 }
572}
573
574impl CoinbaseStackData {
575 pub fn empty() -> Self {
576 let empty = poseidon::hash::hash_noinputs(&NO_INPUT_COINBASE_STACK);
579 MinaBasePendingCoinbaseCoinbaseStackStableV1(empty.into()).into()
580 }
581}
582
583impl CoinbaseStackHash {
584 pub fn zero() -> Self {
585 MinaBasePendingCoinbaseStackHashStableV1(BigInt::zero()).into()
586 }
587}
588
589impl StagedLedgerHashAuxHash {
590 pub fn zero() -> Self {
591 crate::string::ByteString::from(vec![0; 32]).into()
592 }
593}
594
595impl StagedLedgerHashPendingCoinbaseAux {
596 pub fn zero() -> Self {
597 crate::string::ByteString::from(vec![0; 32]).into()
598 }
599}
600
601impl ConsensusVrfOutputTruncatedStableV1 {
602 pub fn zero() -> Self {
603 Self(crate::string::ByteString::from(vec![0; 32]))
604 }
605}
606
607impl MinaBaseStagedLedgerHashNonSnarkStableV1 {
608 pub fn zero(genesis_ledger_hash: LedgerHash) -> Self {
609 Self {
610 ledger_hash: genesis_ledger_hash,
611 aux_hash: StagedLedgerHashAuxHash::zero(),
612 pending_coinbase_aux: StagedLedgerHashPendingCoinbaseAux::zero(),
613 }
614 }
615}
616
617impl From<mina_curves::pasta::Fp> for LedgerHash {
618 fn from(value: mina_curves::pasta::Fp) -> Self {
619 MinaBaseLedgerHash0StableV1(value.into()).into()
620 }
621}
622
623impl From<&mina_curves::pasta::Fp> for LedgerHash {
624 fn from(value: &mina_curves::pasta::Fp) -> Self {
625 MinaBaseLedgerHash0StableV1(value.into()).into()
626 }
627}
628
629impl MinaBaseStagedLedgerHashStableV1 {
630 pub fn zero(
631 genesis_ledger_hash: LedgerHash,
632 empty_pending_coinbase_hash: PendingCoinbaseHash,
633 ) -> Self {
634 Self {
635 non_snark: MinaBaseStagedLedgerHashNonSnarkStableV1::zero(genesis_ledger_hash),
636 pending_coinbase_hash: empty_pending_coinbase_hash,
637 }
638 }
639}
640
641impl MinaBasePendingCoinbaseUpdateStableV1 {
642 pub fn zero() -> Self {
643 Self {
644 action: MinaBasePendingCoinbaseUpdateActionStableV1::UpdateNone,
645 coinbase_amount: CurrencyAmountStableV1(0u64.into()),
646 }
647 }
648}
649
650impl MinaBasePendingCoinbaseStackVersionedStableV1 {
651 pub fn empty() -> Self {
652 Self {
653 data: CoinbaseStackData::empty(),
654 state: MinaBasePendingCoinbaseStateStackStableV1 {
655 init: CoinbaseStackHash::zero(),
656 curr: CoinbaseStackHash::zero(),
657 },
658 }
659 }
660}
661
662impl ConsensusProofOfStakeDataEpochDataStakingValueVersionedValueStableV1 {
663 pub fn zero(
664 ledger_hash: LedgerHash,
665 total_currency: CurrencyAmountStableV1,
666 seed: EpochSeed,
667 ) -> Self {
668 Self {
669 ledger: MinaBaseEpochLedgerValueStableV1 {
670 hash: ledger_hash,
671 total_currency,
672 },
673 seed,
674 start_checkpoint: StateHash::zero(),
675 lock_checkpoint: StateHash::zero(),
676 epoch_length: 1.into(),
677 }
678 }
679}
680
681impl ConsensusProofOfStakeDataEpochDataNextValueVersionedValueStableV1 {
682 pub fn zero(
683 ledger_hash: LedgerHash,
684 total_currency: CurrencyAmountStableV1,
685 seed: EpochSeed,
686 ) -> Self {
687 Self {
688 ledger: MinaBaseEpochLedgerValueStableV1 {
689 hash: ledger_hash,
690 total_currency,
691 },
692 seed,
693 start_checkpoint: StateHash::zero(),
694 lock_checkpoint: StateHash::zero(),
695 epoch_length: 1.into(),
696 }
697 }
698}
699
700impl AsRef<BigInteger256> for LedgerHash {
701 fn as_ref(&self) -> &BigInteger256 {
702 self.0.as_ref()
703 }
704}
705
706impl Default for TokenIdKeyHash {
707 fn default() -> Self {
708 MinaBaseAccountIdDigestStableV1(BigInt::one()).into()
709 }
710}
711
712#[derive(
713 Clone,
714 Debug,
715 PartialEq,
716 Eq,
717 PartialOrd,
718 Ord,
719 Serialize,
720 Deserialize,
721 BinProtRead,
722 BinProtWrite,
723 MallocSizeOf,
724)]
725pub struct NonZeroCurvePointWithVersions {
726 x: Versioned<crate::bigint::BigInt, 1>,
727 is_odd: bool,
728}
729
730impl From<NonZeroCurvePointUncompressedStableV1> for Versioned<NonZeroCurvePointWithVersions, 1> {
731 fn from(source: NonZeroCurvePointUncompressedStableV1) -> Self {
732 NonZeroCurvePointWithVersions {
733 x: source.x.into(),
734 is_odd: source.is_odd,
735 }
736 .into()
737 }
738}
739
740impl From<Versioned<NonZeroCurvePointWithVersions, 1>> for NonZeroCurvePointUncompressedStableV1 {
741 fn from(source: Versioned<NonZeroCurvePointWithVersions, 1>) -> Self {
742 let source = source.into_inner();
743 Self {
744 x: source.x.into_inner(),
745 is_odd: source.is_odd,
746 }
747 }
748}
749
750pub type NonZeroCurvePoint = Base58CheckOfBinProt<
751 NonZeroCurvePointUncompressedStableV1,
752 Versioned<NonZeroCurvePointWithVersions, 1>,
753 { crate::b58version::NON_ZERO_CURVE_POINT_COMPRESSED },
754>;
755
756#[cfg(feature = "openapi")]
757const _: () = {
758 impl utoipa::PartialSchema for NonZeroCurvePoint {
759 fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
760 <String as utoipa::PartialSchema>::schema()
761 }
762 }
763 impl utoipa::ToSchema for NonZeroCurvePoint {
764 fn name() -> std::borrow::Cow<'static, str> {
765 std::borrow::Cow::Borrowed("NonZeroCurvePoint")
766 }
767 }
768};
769
770#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
771pub enum ArchiveTransitionFrontierDiff {
772 BreadcrumbAdded {
773 block: (MinaBlockBlockStableV2, (Option<StateBodyHash>, StateHash)),
774 accounts_accessed: List<(crate::number::UInt64, MinaBaseAccountBinableArgStableV2)>,
775 accounts_created: List<(MinaBaseAccountIdStableV2, CurrencyFeeStableV1)>,
776 tokens_used: List<(MinaBaseTokenIdStableV2, Option<MinaBaseAccountIdStableV2>)>,
777 sender_receipt_chains_from_parent_ledger:
778 List<(MinaBaseAccountIdStableV2, MinaBaseReceiptChainHashStableV1)>,
779 },
780 RootTransitioned(()),
782 BoostrapOf(()),
783}
784
785impl ArchiveTransitionFrontierDiff {
786 pub fn block(&self) -> Option<MinaBlockBlockStableV2> {
787 match self {
788 ArchiveTransitionFrontierDiff::BreadcrumbAdded { block, .. } => Some(block.0.clone()),
790 _ => None,
791 }
792 }
793
794 pub fn accounts_accessed(
795 &self,
796 ) -> List<(crate::number::UInt64, MinaBaseAccountBinableArgStableV2)> {
797 match self {
798 ArchiveTransitionFrontierDiff::BreadcrumbAdded {
799 accounts_accessed, ..
800 } => accounts_accessed.clone(),
801 _ => List::new(),
802 }
803 }
804
805 pub fn accounts_created(&self) -> List<(MinaBaseAccountIdStableV2, CurrencyFeeStableV1)> {
806 match self {
807 ArchiveTransitionFrontierDiff::BreadcrumbAdded {
808 accounts_created, ..
809 } => accounts_created.clone(),
810 _ => List::new(),
811 }
812 }
813
814 pub fn tokens_used(
815 &self,
816 ) -> List<(MinaBaseTokenIdStableV2, Option<MinaBaseAccountIdStableV2>)> {
817 match self {
818 ArchiveTransitionFrontierDiff::BreadcrumbAdded { tokens_used, .. } => {
819 tokens_used.clone()
820 }
821 _ => List::new(),
822 }
823 }
824}
825
826#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
827pub enum ArchiveRpc {
828 SendDiff(ArchiveTransitionFrontierDiff),
829}
830
831#[derive(Clone, Debug, PartialEq, BinProtRead, BinProtWrite)]
832pub struct PrecomputedBlockProof(pub MinaBaseProofStableV2);
833
834impl Serialize for PrecomputedBlockProof {
835 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
836 where
837 S: serde::ser::Serializer,
838 {
839 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
840 use binprot::BinProtWrite;
841 let mut buf = Vec::new();
842 self.0
843 .binprot_write(&mut buf)
844 .map_err(serde::ser::Error::custom)?;
845 let base64_data = URL_SAFE.encode(&buf);
846 serializer.serialize_str(&base64_data)
847 }
848}
849
850impl<'de> Deserialize<'de> for PrecomputedBlockProof {
851 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
852 where
853 D: serde::de::Deserializer<'de>,
854 {
855 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
856 let base64_data = String::deserialize(deserializer)?;
857 let binprot_data = URL_SAFE
858 .decode(&base64_data)
859 .map_err(serde::de::Error::custom)?;
860 let mut read = binprot_data.as_slice();
861 let proof: MinaBaseProofStableV2 =
862 binprot::BinProtRead::binprot_read(&mut read).map_err(serde::de::Error::custom)?;
863 Ok(PrecomputedBlockProof(proof))
864 }
865}
866
867impl From<MinaBaseProofStableV2> for PrecomputedBlockProof {
868 fn from(value: MinaBaseProofStableV2) -> Self {
869 Self(value)
870 }
871}
872
873#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
874pub struct PrecomputedBlock {
875 pub scheduled_time: BlockTimeTimeStableV1,
876 pub protocol_state: MinaStateProtocolStateValueStableV2,
877 pub protocol_state_proof: PrecomputedBlockProof,
878 pub staged_ledger_diff: StagedLedgerDiffDiffStableV2,
879 pub delta_transition_chain_proof: (
883 StateHash, List<StateBodyHash>, ),
886 pub protocol_version: ProtocolVersionStableV2,
887 #[serde(default)]
888 pub proposed_protocol_version: Option<ProtocolVersionStableV2>,
889 pub accounts_accessed: List<(crate::number::UInt64, MinaBaseAccountBinableArgStableV2)>,
890 pub accounts_created: List<(MinaBaseAccountIdStableV2, CurrencyFeeStableV1)>,
891 pub tokens_used: List<(MinaBaseTokenIdStableV2, Option<MinaBaseAccountIdStableV2>)>,
892}
893
894#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
895pub struct PrecomputedBlockData {
896 pub version: u32,
897 pub data: PrecomputedBlock,
898}
899
900impl PrecomputedBlock {
901 pub fn with_version(&self, version: u32) -> PrecomputedBlockData {
902 PrecomputedBlockData {
903 version,
904 data: self.clone(),
905 }
906 }
907}
908
909#[cfg(test)]
910mod tests {
911 use binprot::{BinProtRead, BinProtWrite};
912 use serde::{de::DeserializeOwned, Serialize};
913 use std::fmt::Debug;
914
915 use crate::v2::{
916 CoinbaseStackData, CoinbaseStackHash, EpochSeed, LedgerHash, NonZeroCurvePoint,
917 PendingCoinbaseHash, Signature, StagedLedgerHashAuxHash,
918 StagedLedgerHashPendingCoinbaseAux, StateBodyHash, StateHash, TokenIdKeyHash,
919 };
920
921 fn base58check_test<T: Serialize + DeserializeOwned + BinProtRead + BinProtWrite + Debug>(
922 b58: &str,
923 hex: &str,
924 ) {
925 let bin: T = serde_json::from_value(serde_json::json!(b58)).unwrap();
926 let json = serde_json::to_value(&bin).unwrap();
927
928 let mut binprot = Vec::new();
929 bin.binprot_write(&mut binprot).unwrap();
930
931 println!("{b58} => {}", hex::encode(&binprot));
932
933 let binprot1 = hex::decode(hex).unwrap();
934 let mut b = binprot1.as_slice();
935 let from_hex = T::binprot_read(&mut b).unwrap();
936 println!("{hex} => {}", serde_json::to_string(&from_hex).unwrap());
937
938 assert_eq!(hex::encode(&binprot), hex);
939 assert_eq!(json.as_str().unwrap(), b58);
940 }
941
942 macro_rules! b58t {
943 ($name:ident, $ty:ty, $b58:expr, $hex:expr) => {
944 #[test]
945 fn $name() {
946 base58check_test::<$ty>($b58, $hex);
947 }
948 };
949 }
950
951 b58t!(
952 ledger_hash,
953 LedgerHash,
954 "jwrPvAMUNo3EKT2puUk5Fxz6B7apRAoKNTGpAA49t3TRSfzvdrL",
955 "636f5b2d67278e17bc4343c7c23fb4991f8cf0bbbfd8558615b124d5d6254801"
956 );
957
958 b58t!(
959 staged_ledger_hash_aux_hash,
960 StagedLedgerHashAuxHash,
961 "UbhWTJLi4JM5bizFQVPvfMbjh4tCiTUTrNhedn8WdMPR1KHKJh",
962 "203294e118730ad8b7c0f2ab6d74d244eec02cfef221790bb1274fdb3b97854e50"
963 );
964
965 b58t!(
966 epoch_seed,
967 EpochSeed,
968 "2vajKi2Cxx58mByzxbJA3G6gYh1j2BoizW4zzoLcZa3kYECjhaXV",
969 "4d8802db5beb98f13e10475ddc9e718f6890613276331c062f5d71b915d6941d"
970 );
971
972 b58t!(
973 staged_ledger_hash_pending_coinbase_aux,
974 StagedLedgerHashPendingCoinbaseAux,
975 "XgkNHpgSvmF7CyRBGUzcwvCD9daBRhZUDLg3xTvohmTX1mRqHR",
976 "20c922885bfeda2c2568e32fcc595fe0ad2292dcf756be637545bc553f7f7028e8"
977 );
978
979 b58t!(
980 state_hash,
981 StateHash,
982 "3NL7AkynW6hbDrhHTAht1GLG563Fo9fdcEQk1zEyy5XedC6aZTeB",
983 "8d67aadd018581a812623915b13d5c3a6da7dfe8a195172d9bbd206810bc2329"
984 );
985
986 b58t!(
987 state_body_hash,
988 StateBodyHash,
989 "3WtsPNWF7Ua5zbvHEARuEL32KEfMM7pPYNXWVGtTStdYJRYA2rta",
990 "1b11c26e5541d2f719a50f2e5bdcd23e7995883036f3d2e5675dfd3015ec6202"
991 );
992
993 b58t!(
994 pending_coinbase_hash,
995 PendingCoinbaseHash,
996 "2n2EEn3yH1oRU8tCXTjw7dJKHQVcFTkfeDCTpBzum3sZcssPeaVM",
997 "e23a19254e600402e4474371450d498c75a9b3e28c34160d489af61c255f722c"
998 );
999
1000 b58t!(
1001 token_id_key,
1002 TokenIdKeyHash,
1003 "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf",
1004 "0100000000000000000000000000000000000000000000000000000000000000"
1005 );
1006
1007 b58t!(
1016 coinbase_stack_data,
1017 CoinbaseStackData,
1018 "4QNrZFBTDQCPfEZqBZsaPYx8qdaNFv1nebUyCUsQW9QUJqyuD3un",
1019 "35b9d51e5d7c741456f86720731241a8280273cfc6c21668fd7bc6c587d0cc1d"
1020 );
1021
1022 b58t!(
1023 coinbase_stack_hash,
1024 CoinbaseStackHash,
1025 "4Yx5U3t3EYQycZ91yj4478bHkLwGkhDHnPbCY9TxgUk69SQityej",
1026 "0000000000000000000000000000000000000000000000000000000000000000"
1027 );
1028
1029 b58t!(
1030 signature,
1031 Signature,
1032 "7mXS9Y91bWtTYNKuDbxTuG18wUiZLHUySy9Ms8bPyAT9KNnME1q2nctwnvowJi2Y79dnsL18iVSCuaQF1ufUKwUZZKAXHqnF",
1033 "d290f924705fb714e91fedb9bed77e85bce8f5d932c3f4d692b20e4c3e5f9a3343c2baffce9ab0c2391e2f3de8ac891633338d827e6fd4f269331c248029b106"
1034 );
1035
1036 #[test]
1037 fn non_zero_curve_point() {
1038 let b58 = r#""B62qkUHaJUHERZuCHQhXCQ8xsGBqyYSgjQsKnKN5HhSJecakuJ4pYyk""#;
1039
1040 let v = serde_json::from_str::<NonZeroCurvePoint>(&b58)
1041 .unwrap()
1042 .into_inner();
1043 assert_eq!(v.is_odd, false);
1044 assert_eq!(
1045 &hex::encode(&v.x.to_bytes()),
1046 "3c2b5b48c22dc8b8c9d2c9d76a2ceaaf02beabb364301726c3f8e989653af513"
1047 );
1048 }
1049}
1050
1051const SHIFTED_VALUE: &str = "Shifted_value";
1052
1053impl Serialize for PicklesProofProofsVerified2ReprStableV2StatementFp {
1054 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1055 where
1056 S: serde::Serializer,
1057 {
1058 if serializer.is_human_readable() {
1059 let mut serializer = serializer.serialize_tuple(2)?;
1060 match self {
1061 PicklesProofProofsVerified2ReprStableV2StatementFp::ShiftedValue(v) => {
1062 serializer.serialize_element(SHIFTED_VALUE)?;
1063 serializer.serialize_element(v)?;
1064 }
1065 }
1066 serializer.end()
1067 } else {
1068 match self {
1069 PicklesProofProofsVerified2ReprStableV2StatementFp::ShiftedValue(v) => serializer
1070 .serialize_newtype_variant(
1071 "PicklesProofProofsVerified2ReprStableV2StatementFp",
1072 0,
1073 "ShiftedValue",
1074 v,
1075 ),
1076 }
1077 }
1078 }
1079}
1080
1081impl<'de> Deserialize<'de> for PicklesProofProofsVerified2ReprStableV2StatementFp {
1082 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1083 where
1084 D: serde::Deserializer<'de>,
1085 {
1086 struct V;
1087 impl<'de> Visitor<'de> for V {
1088 type Value = PicklesProofProofsVerified2ReprStableV2StatementFp;
1089
1090 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1091 formatter.write_str("tuple of tag and value")
1092 }
1093
1094 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1095 where
1096 A: serde::de::SeqAccess<'de>,
1097 {
1098 match seq.next_element::<String>()? {
1099 Some(v) if &v == SHIFTED_VALUE => {}
1100 Some(v) => {
1101 return Err(serde::de::Error::custom(format!(
1102 "expecting `{SHIFTED_VALUE}`, got `{v}`"
1103 )))
1104 }
1105 None => return Err(serde::de::Error::custom("expecting a tag")),
1106 }
1107 match seq.next_element::<BigInt>()? {
1108 Some(v) => {
1109 Ok(PicklesProofProofsVerified2ReprStableV2StatementFp::ShiftedValue(v))
1110 }
1111 None => return Err(serde::de::Error::custom("expecting a value")),
1112 }
1113 }
1114 }
1115
1116 if deserializer.is_human_readable() {
1117 deserializer.deserialize_tuple(2, V)
1118 } else {
1119 #[derive(Deserialize)]
1120 pub enum PicklesProofProofsVerified2ReprStableV2StatementFp {
1121 ShiftedValue(crate::bigint::BigInt),
1122 }
1123 let PicklesProofProofsVerified2ReprStableV2StatementFp::ShiftedValue(v) =
1124 Deserialize::deserialize(deserializer)?;
1125 Ok(Self::ShiftedValue(v))
1126 }
1127 }
1128}
1129
1130impl Serialize for ConsensusVrfOutputTruncatedStableV1 {
1131 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1132 where
1133 S: serde::Serializer,
1134 {
1135 if serializer.is_human_readable() {
1136 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
1138 let base64_data = URL_SAFE.encode(&self.0 .0);
1139 serializer.serialize_str(&base64_data)
1140 } else {
1141 serializer.serialize_newtype_struct("ConsensusVrfOutputTruncatedStableV1", &self.0)
1142 }
1143 }
1144}
1145
1146impl<'de> Deserialize<'de> for ConsensusVrfOutputTruncatedStableV1 {
1147 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1148 where
1149 D: serde::Deserializer<'de>,
1150 {
1151 if deserializer.is_human_readable() {
1152 use base64::{engine::general_purpose::URL_SAFE, Engine as _};
1154 let base64_data = String::deserialize(deserializer)?;
1155 URL_SAFE
1156 .decode(&base64_data)
1157 .map(|vec| ByteString::from(vec))
1158 .map_err(|e| serde::de::Error::custom(format!("Error deserializing vrf: {e}")))
1159 } else {
1160 Deserialize::deserialize(deserializer)
1161 }
1162 .map(Self)
1163 }
1164}
1165
1166impl MinaBaseVerificationKeyWireStableV1 {
1167 pub fn to_base64(&self) -> Result<String, conv::Error> {
1168 let mut buffer: Vec<u8> = Vec::new();
1169 self.binprot_write(&mut buffer)?;
1170 use base64::{engine::general_purpose::STANDARD, Engine as _};
1171
1172 let base64_data = STANDARD.encode(buffer);
1173 Ok(base64_data)
1174 }
1175
1176 pub fn from_base64(base64_data: &str) -> Result<Self, conv::Error> {
1177 use base64::{engine::general_purpose::STANDARD, Engine as _};
1178 let decoded_data = STANDARD.decode(base64_data)?;
1179 let res = MinaBaseVerificationKeyWireStableV1::binprot_read(&mut decoded_data.as_slice())?;
1180 Ok(res)
1181 }
1182}
1183
1184impl MinaBaseSignedCommandStableV2 {
1186 pub fn to_base64(&self) -> Result<String, conv::Error> {
1187 const COMMAND_VERSION_TAG: u8 = 2;
1188
1189 let mut buffer: Vec<u8> = Vec::new();
1190 COMMAND_VERSION_TAG.binprot_write(&mut buffer)?;
1191 self.binprot_write(&mut buffer)?;
1192 use base64::{engine::general_purpose::STANDARD, Engine as _};
1193
1194 let base64_data = STANDARD.encode(buffer);
1195 Ok(base64_data)
1196 }
1197
1198 pub fn from_base64(base64_data: &str) -> Result<Self, conv::Error> {
1199 use base64::{engine::general_purpose::STANDARD, Engine as _};
1200 let decoded_data = STANDARD.decode(&base64_data)?;
1201 let res = MinaBaseSignedCommandStableV2::binprot_read(&mut decoded_data[1..].as_ref())?;
1202 Ok(res)
1203 }
1204}
1205
1206impl MinaBaseZkappCommandTStableV1WireStableV1 {
1208 pub fn to_base64(&self) -> Result<String, conv::Error> {
1209 const ZKAPP_VERSION_TAG: u8 = 1;
1210
1211 let mut buffer: Vec<u8> = Vec::new();
1212 ZKAPP_VERSION_TAG.binprot_write(&mut buffer)?;
1213 self.binprot_write(&mut buffer)?;
1214 use base64::{engine::general_purpose::STANDARD, Engine as _};
1215
1216 let base64_data = STANDARD.encode(buffer);
1217 Ok(base64_data)
1218 }
1219
1220 pub fn from_base64(base64_data: &str) -> Result<Self, conv::Error> {
1221 use base64::{engine::general_purpose::STANDARD, Engine as _};
1222 let decoded_data = STANDARD.decode(&base64_data)?;
1223 let res = MinaBaseZkappCommandTStableV1WireStableV1::binprot_read(
1224 &mut decoded_data[1..].as_ref(),
1225 )?;
1226 Ok(res)
1227 }
1228}
1229
1230impl Serialize for ConsensusBodyReferenceStableV1 {
1231 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1232 where
1233 S: serde::ser::Serializer,
1234 {
1235 if serializer.is_human_readable() {
1236 let hex_string = hex::encode(&self.0);
1237 serializer.serialize_str(&hex_string)
1238 } else {
1239 self.0.serialize(serializer)
1240 }
1241 }
1242}
1243
1244impl<'de> Deserialize<'de> for ConsensusBodyReferenceStableV1 {
1245 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1246 where
1247 D: serde::de::Deserializer<'de>,
1248 {
1249 if deserializer.is_human_readable() {
1250 let hex_string = String::deserialize(deserializer)?;
1251 let decoded_bytes = hex::decode(&hex_string).map_err(serde::de::Error::custom)?;
1252 Ok(ConsensusBodyReferenceStableV1(
1253 crate::string::ByteString::from(decoded_bytes),
1254 ))
1255 } else {
1256 let inner_value = crate::string::ByteString::deserialize(deserializer)?;
1257 Ok(ConsensusBodyReferenceStableV1(inner_value))
1258 }
1259 }
1260}
1261
1262impl<'de> Deserialize<'de> for MinaNumbersGlobalSlotSinceGenesisMStableV1 {
1264 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1265 where
1266 D: serde::de::Deserializer<'de>,
1267 {
1268 let value = UnsignedExtendedUInt32StableV1::deserialize(deserializer)?;
1269 Ok(MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1270 value,
1271 ))
1272 }
1273}
1274
1275impl<'de> Deserialize<'de> for MinaNumbersGlobalSlotSinceHardForkMStableV1 {
1277 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1278 where
1279 D: serde::de::Deserializer<'de>,
1280 {
1281 let value = UnsignedExtendedUInt32StableV1::deserialize(deserializer)?;
1282 Ok(MinaNumbersGlobalSlotSinceHardForkMStableV1::SinceHardFork(
1283 value,
1284 ))
1285 }
1286}
1287
1288pub type MerkleTreePath = Vec<MerkleTreeNode>;
1289
1290#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
1291#[polymorphic_variant]
1292pub enum MerkleTreeNode {
1293 Left(BigInt),
1294 Right(BigInt),
1295}
1296
1297impl ConsensusProofOfStakeDataConsensusStateValueStableV2 {
1298 pub fn global_slot(&self) -> u32 {
1299 match &self.curr_global_slot_since_hard_fork.slot_number {
1300 super::MinaNumbersGlobalSlotSinceHardForkMStableV1::SinceHardFork(s) => s.as_u32(),
1301 }
1302 }
1303}
1304
1305impl AsRef<str> for SgnStableV1 {
1306 fn as_ref(&self) -> &str {
1307 match self {
1308 SgnStableV1::Pos => "Pos",
1309 SgnStableV1::Neg => "Neg",
1310 }
1311 }
1312}
1313
1314impl Serialize for SgnStableV1 {
1315 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1316 where
1317 S: serde::Serializer,
1318 {
1319 if serializer.is_human_readable() {
1320 let mut tuple = serializer.serialize_tuple(1)?;
1321 tuple.serialize_element(self.as_ref())?;
1322 tuple.end()
1323 } else {
1324 match *self {
1325 SgnStableV1::Pos => {
1326 Serializer::serialize_unit_variant(serializer, "SgnStableV1", 0u32, "Pos")
1327 }
1328 SgnStableV1::Neg => {
1329 Serializer::serialize_unit_variant(serializer, "SgnStableV1", 1u32, "Neg")
1330 }
1331 }
1332 }
1333 }
1334}
1335
1336impl<'de> Deserialize<'de> for SgnStableV1 {
1337 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1338 where
1339 D: serde::Deserializer<'de>,
1340 {
1341 if deserializer.is_human_readable() {
1342 struct V;
1343
1344 impl<'de> Visitor<'de> for V {
1345 type Value = String;
1346
1347 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1348 formatter.write_str("`Pos` or `Neg`")?;
1349 panic!("foo")
1350 }
1351
1352 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
1353 where
1354 E: serde::de::Error,
1355 {
1356 Ok(v)
1357 }
1358
1359 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1360 where
1361 A: serde::de::SeqAccess<'de>,
1362 {
1363 let Some(elt) = seq.next_element()? else {
1364 return Err(serde::de::Error::custom("No tag"));
1365 };
1366 Ok(elt)
1367 }
1368 }
1369 let v = deserializer.deserialize_tuple(1, V)?;
1370 match v.as_str() {
1371 "Pos" => Ok(SgnStableV1::Pos),
1372 "Neg" => Ok(SgnStableV1::Neg),
1373 _ => Err(serde::de::Error::custom(format!("Invalid tag {v}"))),
1374 }
1375 } else {
1376 #[derive(Deserialize)]
1377 enum _SgnStableV1 {
1378 Pos,
1379 Neg,
1380 }
1381
1382 let s: _SgnStableV1 = Deserialize::deserialize(deserializer)?;
1383 match s {
1384 _SgnStableV1::Pos => Ok(SgnStableV1::Pos),
1385 _SgnStableV1::Neg => Ok(SgnStableV1::Neg),
1386 }
1387 }
1388 }
1389}
1390
1391const PRECISION: usize = 9;
1392const PRECISION_EXP: u64 = 10u64.pow(PRECISION as u32);
1393
1394impl Serialize for CurrencyFeeStableV1 {
1395 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1396 where
1397 S: serde::ser::Serializer,
1398 {
1399 let amount = self.0 .0.as_u64();
1400 let whole = amount / PRECISION_EXP;
1401 let remainder = amount % PRECISION_EXP;
1402
1403 if remainder == 0 {
1404 serializer.serialize_str(&whole.to_string())
1405 } else {
1406 let tmp = format!("{:0width$}", remainder, width = PRECISION);
1407 let fractional_str = tmp.trim_end_matches('0');
1408 serializer.serialize_str(&format!("{}.{}", whole, fractional_str))
1409 }
1410 }
1411}
1412
1413impl<'de> Deserialize<'de> for CurrencyFeeStableV1 {
1414 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1415 where
1416 D: serde::de::Deserializer<'de>,
1417 {
1418 let s: String = Deserialize::deserialize(deserializer)?;
1419 let parts: Vec<&str> = s.split('.').collect();
1420 let result = match parts.as_slice() {
1421 [whole] => format!("{}{}", whole, "0".repeat(PRECISION)),
1422 [whole, decimal] => {
1423 let decimal_length = decimal.len();
1424 if decimal_length > PRECISION {
1425 format!("{}{}", whole, &decimal[0..PRECISION])
1426 } else {
1427 format!(
1428 "{}{}{}",
1429 whole,
1430 decimal,
1431 "0".repeat(PRECISION - decimal_length)
1432 )
1433 }
1434 }
1435 _ => return Err(serde::de::Error::custom("Invalid currency input")),
1436 };
1437 let fee_in_nanomina: u64 = result.parse().map_err(serde::de::Error::custom)?;
1438 Ok(CurrencyFeeStableV1(
1439 UnsignedExtendedUInt64Int64ForVersionTagsStableV1(fee_in_nanomina.into()),
1440 ))
1441 }
1442}
1443
1444#[cfg(test)]
1445mod tests_currency_fee_serialization {
1446 use super::*;
1447 use serde_json;
1448
1449 #[test]
1450 fn test_correct_serialization() {
1451 let amount = 1_000_000u64;
1452 let currency = CurrencyFeeStableV1(amount.into());
1453
1454 let serialized = serde_json::to_string(¤cy).unwrap();
1455 assert_eq!(serialized, "\"0.001\"", "Serialization output is incorrect");
1456 }
1457
1458 #[test]
1459 fn test_zero_remainder() {
1460 let amount = 1_000_000_000u64;
1461 let currency = CurrencyFeeStableV1(amount.into());
1462
1463 let serialized = serde_json::to_string(¤cy).unwrap();
1464 assert_eq!(
1465 serialized, "\"1\"",
1466 "Serialization output is incorrect for whole numbers"
1467 );
1468 }
1469
1470 #[test]
1471 fn test_fractional_serialization() {
1472 let amount = 1_234_567_890u64;
1473 let currency = CurrencyFeeStableV1(amount.into());
1474
1475 let serialized = serde_json::to_string(¤cy).unwrap();
1476 assert_eq!(
1477 serialized, "\"1.23456789\"",
1478 "Serialization output is incorrect for fractional numbers"
1479 );
1480 }
1481
1482 #[test]
1483 fn test_trailing_zeros() {
1484 let amount = 1_230_000_000u64;
1485 let currency = CurrencyFeeStableV1(amount.into());
1486
1487 let serialized = serde_json::to_string(¤cy).unwrap();
1488 assert_eq!(
1489 serialized, "\"1.23\"",
1490 "Serialization output is incorrect when fractional part has trailing zeros"
1491 );
1492 }
1493
1494 #[test]
1495 fn test_deserialization_correct_serialization() {
1496 let serialized = "\"0.001\"";
1497 let currency: CurrencyFeeStableV1 = serde_json::from_str(serialized).unwrap();
1498 let expected_amount = 1_000_000u64;
1499 assert_eq!(
1500 currency,
1501 CurrencyFeeStableV1(expected_amount.into()),
1502 "Deserialization output is incorrect"
1503 );
1504 }
1505
1506 #[test]
1507 fn test_deserialization_zero_remainder() {
1508 let serialized = "\"1\"";
1509 let currency: CurrencyFeeStableV1 = serde_json::from_str(serialized).unwrap();
1510 let expected_amount = 1_000_000_000u64;
1511 assert_eq!(
1512 currency,
1513 CurrencyFeeStableV1(expected_amount.into()),
1514 "Deserialization output is incorrect for whole numbers"
1515 );
1516 }
1517
1518 #[test]
1519 fn test_deserialization_fractional() {
1520 let serialized = "\"1.23456789\"";
1521 let currency: CurrencyFeeStableV1 = serde_json::from_str(serialized).unwrap();
1522 let expected_amount = 1_234_567_890u64;
1523 assert_eq!(
1524 currency,
1525 CurrencyFeeStableV1(expected_amount.into()),
1526 "Deserialization output is incorrect for fractional numbers"
1527 );
1528 }
1529
1530 #[test]
1531 fn test_deserialization_trailing_zeros() {
1532 let serialized = "\"1.23\"";
1533 let currency: CurrencyFeeStableV1 = serde_json::from_str(serialized).unwrap();
1534 let expected_amount = 1_230_000_000u64;
1535 assert_eq!(
1536 currency,
1537 CurrencyFeeStableV1(expected_amount.into()),
1538 "Deserialization output is incorrect when fractional part has trailing zeros"
1539 );
1540 }
1541
1542 #[test]
1543 fn test_deserialization_truncates_extra_decimals() {
1544 let serialized = "\"0.1234567890123\""; let currency: CurrencyFeeStableV1 = serde_json::from_str(serialized).unwrap();
1546 let expected_amount = 123_456_789u64; assert_eq!(
1548 currency,
1549 CurrencyFeeStableV1(expected_amount.into()),
1550 "Deserialization did not correctly truncate extra decimal places"
1551 );
1552 }
1553
1554 #[test]
1555 fn test_deserialization_invalid_number() {
1556 let serialized = "\"abc\"";
1557 let result: Result<CurrencyFeeStableV1, _> = serde_json::from_str(serialized);
1558 assert!(
1559 result.is_err(),
1560 "Deserialization should fail for invalid number strings"
1561 );
1562 }
1563}
1564
1565#[cfg(test)]
1566mod tests_sgn {
1567 use crate::v2::SgnStableV1;
1568
1569 #[test]
1570 fn test_json() {
1571 assert_eq!(
1572 serde_json::to_value(&SgnStableV1::Pos).unwrap(),
1573 serde_json::json!(["Pos"])
1574 );
1575 assert_eq!(
1576 serde_json::to_value(&SgnStableV1::Neg).unwrap(),
1577 serde_json::json!(["Neg"])
1578 );
1579
1580 assert_eq!(
1581 serde_json::from_value::<SgnStableV1>(serde_json::json!(["Pos"])).unwrap(),
1582 SgnStableV1::Pos
1583 );
1584 assert_eq!(
1585 serde_json::from_value::<SgnStableV1>(serde_json::json!(["Neg"])).unwrap(),
1586 SgnStableV1::Neg
1587 );
1588 }
1589}
1590
1591#[derive(
1597 Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite, MallocSizeOf,
1598)]
1599pub struct SignedAmount {
1600 pub magnitude: CurrencyFeeStableV1,
1601 pub sgn: SgnStableV1,
1602}
1603
1604#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
1614pub struct MinaBaseFeeExcessStableV1(pub TokenFeeExcess, pub TokenFeeExcess);
1615
1616#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
1617pub struct TokenFeeExcess {
1618 pub token: TokenIdKeyHash,
1619 pub amount: SignedAmount,
1620}
1621
1622impl Default for NonZeroCurvePointUncompressedStableV1 {
1623 fn default() -> Self {
1624 Self {
1625 x: Default::default(),
1626 is_odd: false,
1627 }
1628 }
1629}
1630
1631impl MinaNumbersGlobalSlotSinceGenesisMStableV1 {
1632 pub fn as_u32(&self) -> u32 {
1633 let Self::SinceGenesis(slot) = self;
1634 slot.as_u32()
1635 }
1636}
1637
1638impl MinaNumbersGlobalSlotSinceHardForkMStableV1 {
1639 pub fn as_u32(&self) -> u32 {
1640 let Self::SinceHardFork(slot) = self;
1641 slot.as_u32()
1642 }
1643}
1644
1645impl MinaNumbersGlobalSlotSpanStableV1 {
1646 pub fn as_u32(&self) -> u32 {
1647 let Self::GlobalSlotSpan(slot) = self;
1648 slot.as_u32()
1649 }
1650}
1651
1652impl From<u32> for UnsignedExtendedUInt32StableV1 {
1653 fn from(value: u32) -> Self {
1654 Self(value.into())
1655 }
1656}
1657
1658impl From<u64> for UnsignedExtendedUInt64Int64ForVersionTagsStableV1 {
1659 fn from(value: u64) -> Self {
1660 Self(value.into())
1661 }
1662}
1663
1664impl From<&PicklesProofProofsVerifiedMaxStableV2> for PicklesProofProofsVerified2ReprStableV2 {
1665 fn from(value: &PicklesProofProofsVerifiedMaxStableV2) -> Self {
1666 let PicklesProofProofsVerifiedMaxStableV2 {
1667 statement,
1668 prev_evals,
1669 proof,
1670 } = value;
1671
1672 Self {
1673 statement: statement.clone(),
1674 prev_evals: prev_evals.clone(),
1675 proof: proof.clone(),
1676 }
1677 }
1678}
1679
1680impl std::fmt::Debug for UnsignedExtendedUInt32StableV1 {
1681 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1682 let Self(inner) = self;
1683 f.write_fmt(format_args!("UnsignedExtendedUInt32StableV1({:?})", inner))
1685 }
1686}
1687
1688impl std::fmt::Debug for UnsignedExtendedUInt64Int64ForVersionTagsStableV1 {
1689 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1690 let Self(inner) = self;
1691 f.write_fmt(format_args!(
1693 "UnsignedExtendedUInt64Int64ForVersionTagsStableV1({:?})",
1694 inner
1695 ))
1696 }
1697}
1698
1699impl MinaBaseProtocolConstantsCheckedValueStableV1 {
1700 const fn default_constants() -> Self {
1701 const fn from_u32(v: u32) -> UnsignedExtendedUInt32StableV1 {
1702 UnsignedExtendedUInt32StableV1(Number(v))
1703 }
1704
1705 Self {
1706 k: from_u32(290),
1707 slots_per_epoch: from_u32(7140),
1708 slots_per_sub_window: from_u32(7),
1709 grace_period_slots: from_u32(2160),
1710 delta: from_u32(0),
1711 genesis_state_timestamp: BlockTimeTimeStableV1(
1712 UnsignedExtendedUInt64Int64ForVersionTagsStableV1(Number(1600251300000)), ),
1714 }
1715 }
1716}
1717
1718impl Default for MinaBaseProtocolConstantsCheckedValueStableV1 {
1719 fn default() -> Self {
1720 Self::default_constants()
1721 }
1722}
1723
1724pub const PROTOCOL_CONSTANTS: MinaBaseProtocolConstantsCheckedValueStableV1 =
1725 MinaBaseProtocolConstantsCheckedValueStableV1::default_constants();
1726
1727impl From<OffsetDateTime> for BlockTimeTimeStableV1 {
1728 fn from(value: OffsetDateTime) -> Self {
1729 debug_assert!(value.unix_timestamp() >= 0);
1730 BlockTimeTimeStableV1((value.unix_timestamp() as u64 * 1000).into())
1731 }
1732}
1733
1734impl AsRef<MinaBaseUserCommandStableV2> for MinaBaseUserCommandStableV2 {
1735 fn as_ref(&self) -> &MinaBaseUserCommandStableV2 {
1736 self
1737 }
1738}
1739
1740impl MinaBlockHeaderStableV2 {
1741 pub fn genesis_state_hash(&self) -> &StateHash {
1742 &self.protocol_state.body.genesis_state_hash
1743 }
1744}
1745
1746impl StagedLedgerDiffBodyStableV1 {
1747 pub fn diff(&self) -> &StagedLedgerDiffDiffDiffStableV2 {
1748 &self.staged_ledger_diff.diff
1749 }
1750 pub fn commands_iter<'a>(
1751 &'a self,
1752 ) -> Box<dyn 'a + Iterator<Item = &'a StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2B>>
1753 {
1754 let diff = self.diff();
1755 let iter = diff.0.commands.iter();
1756 if let Some(_1) = diff.1.as_ref() {
1757 Box::new(iter.chain(_1.commands.iter()))
1758 } else {
1759 Box::new(iter)
1760 }
1761 }
1762
1763 pub fn transactions(&self) -> impl Iterator<Item = &MinaBaseUserCommandStableV2> {
1764 self.commands_iter().map(|command| &command.data)
1765 }
1766
1767 pub fn tranasctions_with_status(
1768 &self,
1769 ) -> impl Iterator<
1770 Item = (
1771 &MinaBaseUserCommandStableV2,
1772 &MinaBaseTransactionStatusStableV2,
1773 ),
1774 > {
1775 self.commands_iter()
1776 .map(|command| (&command.data, &command.status))
1777 }
1778
1779 pub fn coinbase_fee_transfers_iter(
1780 &self,
1781 ) -> impl Iterator<Item = &StagedLedgerDiffDiffFtStableV1> {
1782 let diff = self.diff();
1783 let mut coinbases = Vec::with_capacity(4);
1784 match &diff.0.coinbase {
1785 StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2Coinbase::Zero => {}
1786 StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2Coinbase::One(v) => {
1787 coinbases.push(v.as_ref());
1788 }
1789 StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2Coinbase::Two(v) => {
1790 match v.as_ref() {
1791 None => {}
1792 Some((v1, v2)) => {
1793 coinbases.push(Some(v1));
1794 coinbases.push(v2.as_ref());
1795 }
1796 }
1797 }
1798 }
1799
1800 if let Some(StagedLedgerDiffDiffPreDiffWithAtMostOneCoinbaseStableV2Coinbase::One(v)) =
1801 diff.1.as_ref().map(|v| &v.coinbase)
1802 {
1803 coinbases.push(v.as_ref());
1804 }
1805
1806 coinbases.into_iter().flatten()
1807 }
1808
1809 pub fn completed_works_iter<'a>(
1810 &'a self,
1811 ) -> Box<dyn 'a + Iterator<Item = &'a TransactionSnarkWorkTStableV2>> {
1812 let diff = self.diff();
1813 let _0 = &diff.0;
1814 if let Some(_1) = diff.1.as_ref() {
1815 Box::new(_0.completed_works.iter().chain(_1.completed_works.iter()))
1816 } else {
1817 Box::new(_0.completed_works.iter())
1818 }
1819 }
1820
1821 pub fn completed_works_count(&self) -> usize {
1822 self.diff().0.completed_works.len()
1823 + self
1824 .diff()
1825 .1
1826 .as_ref()
1827 .map_or(0, |d| d.completed_works.len())
1828 }
1829
1830 pub fn has_coinbase(&self) -> bool {
1831 let (first_pre_diff, second_pre_diff) = (
1832 self.diff().0.coinbase.clone(),
1833 self.diff().1.as_ref().map_or(
1834 StagedLedgerDiffDiffPreDiffWithAtMostOneCoinbaseStableV2Coinbase::Zero,
1835 |v| v.coinbase.clone(),
1836 ),
1837 );
1838
1839 match (first_pre_diff, second_pre_diff) {
1840 (
1841 StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2Coinbase::Zero,
1842 StagedLedgerDiffDiffPreDiffWithAtMostOneCoinbaseStableV2Coinbase::Zero,
1843 ) => false,
1844 _ => true,
1845 }
1846 }
1847
1848 pub fn fees_sum(&self) -> u64 {
1849 self.commands_iter()
1850 .map(|v| match &v.data {
1851 MinaBaseUserCommandStableV2::SignedCommand(v) => v.payload.common.fee.as_u64(),
1852 MinaBaseUserCommandStableV2::ZkappCommand(v) => v.fee_payer.body.fee.as_u64(),
1853 })
1854 .sum()
1855 }
1856
1857 pub fn snark_fees_sum(&self) -> u64 {
1858 self.completed_works_iter().map(|v| v.fee.as_u64()).sum()
1859 }
1860}
1861
1862impl From<PicklesProofProofsVerifiedMaxStableV2> for PicklesProofProofsVerified2ReprStableV2 {
1865 fn from(value: PicklesProofProofsVerifiedMaxStableV2) -> Self {
1866 Self {
1867 statement: value.statement,
1868 prev_evals: value.prev_evals,
1869 proof: value.proof,
1870 }
1871 }
1872}
1873
1874impl From<PicklesProofProofsVerified2ReprStableV2> for PicklesProofProofsVerifiedMaxStableV2 {
1875 fn from(value: PicklesProofProofsVerified2ReprStableV2) -> Self {
1876 Self {
1877 statement: value.statement,
1878 prev_evals: value.prev_evals,
1879 proof: value.proof,
1880 }
1881 }
1882}
1883
1884impl std::fmt::Display for SgnStableV1 {
1885 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1886 match self {
1887 SgnStableV1::Pos => write!(f, "Positive"),
1888 SgnStableV1::Neg => write!(f, "Negative"),
1889 }
1890 }
1891}
1892
1893impl std::str::FromStr for SgnStableV1 {
1894 type Err = String;
1895
1896 fn from_str(s: &str) -> Result<Self, Self::Err> {
1897 match s {
1898 "Positive" => Ok(SgnStableV1::Pos),
1899 "Negative" => Ok(SgnStableV1::Neg),
1900 _ => Err("Invalid Sgn string, expected Positive or Negative".to_string()),
1901 }
1902 }
1903}
1904
1905#[cfg(test)]
1906mod test {
1907 use binprot::BinProtRead;
1908
1909 use crate::v2;
1910
1911 #[test]
1912 fn test_zkapp_with_sig_auth_hash() {
1913 let expexcted = "AbliNXLg4Keq0ZJyxK/QNAx8SxrJeffYytk5lbcTF9s9Af0A4fUFAP2+oQMA48vntxcABLty3SXWjvuadrLtBjcsxT1oJ3C2hwS/LDh364LKUxrLe3uF/9lr8VlW/J+ctbiI+m9I61sb9BC/AAG5YjVy4OCnqtGScsSv0DQMfEsayXn32MrZOZW3ExfbPQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAEBAQEBAQH9AJQ1dwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAAAAAePL57cXAAS7ct0l1o77mnay7QY3LMU9aCdwtocEvyw4d+uCylMay3t7hf/Za/FZVvyfnLW4iPpvSOtbG/QQvwAAAcwXZjv4NJwWwlJhFZPh2AK+o0dKOpIy1a6CXlskW7gmAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAQEBAQEBAf0AlDV3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQAAAAICAAAAACIBFlRlc3QgWktBcHAgdG8gUmVjZWl2ZXIAAAAAAAAAAAAA".to_string();
1914 let bytes = include_bytes!("../../../../tests/files/zkapps/with_sig_auth.bin");
1915 let zkapp =
1916 v2::MinaBaseZkappCommandTStableV1WireStableV1::binprot_read(&mut bytes.as_slice())
1917 .unwrap();
1918
1919 let zkapp_id = zkapp.to_base64().unwrap();
1920 assert_eq!(expexcted, zkapp_id);
1921 }
1922
1923 #[test]
1924 fn test_verification_key_base64_decode() {
1925 use base64::{engine::general_purpose::STANDARD, Engine as _};
1926 let verification_key_encoded = "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";
1928
1929 let decoded = STANDARD.decode(verification_key_encoded).unwrap();
1930 let verification_key =
1931 v2::MinaBaseVerificationKeyWireStableV1::binprot_read(&mut decoded.as_slice());
1932 assert!(verification_key.is_ok());
1933 }
1934
1935 #[test]
1936 fn test_archive_breadcrumb_deserialization() {
1937 let breadcrumb_bytes = include_bytes!("../../../../tests/files/archive-breadcrumb/3NK56ZbCS31qb8SvCtCCYza4beRDtKgXA2JL6s3evKouG2KkKtiy.bin");
1938 let result =
1939 v2::ArchiveTransitionFrontierDiff::binprot_read(&mut breadcrumb_bytes.as_slice());
1940
1941 assert!(result.is_ok());
1942 }
1943}