concordium_rust_sdk/v2/
conversions.rs

1//! Helpers and trait implementations to convert from proto generated types to
2//! their Rust equivalents.
3
4use super::{
5    generated::{self, *},
6    upward::Upward,
7    Require,
8};
9use crate::types::{
10    chain_parameters,
11    queries::{ConcordiumBFTDetails, ProtocolVersionInt},
12    AccountReleaseSchedule, ActiveBakerPoolStatus,
13};
14use chrono::TimeZone;
15use concordium_base::{
16    base,
17    common::{Deserial, Versioned, VERSION_0},
18    id::{
19        constants::{ArCurve, AttributeKind, IpPairing},
20        types::{
21            AccountCredentialWithoutProofs, CredentialDeploymentValues,
22            InitialCredentialDeploymentValues,
23        },
24    },
25    smart_contracts::WasmVersionInt,
26    updates,
27};
28use cooldown::CooldownStatus;
29use std::collections::{BTreeMap, BTreeSet};
30
31fn consume<A: Deserial>(bytes: &[u8]) -> Result<A, tonic::Status> {
32    let mut cursor = std::io::Cursor::new(bytes);
33    let res = A::deserial(&mut cursor);
34    match res {
35        Ok(v) if cursor.position() == bytes.len() as u64 => Ok(v),
36        Err(e) => Err(tonic::Status::internal(format!(
37            "Could not deserialize response: {}",
38            e
39        ))),
40        Ok(_) => Err(tonic::Status::internal(
41            "Could not deserialize response: trailing bytes",
42        )),
43    }
44}
45
46/// Convert from the 0-based protobuf representation to the 1-based internal
47/// representation of a [ProtocolVersionInt].
48fn protocol_version_int_from_enum(tag_number: i32) -> Result<ProtocolVersionInt, tonic::Status> {
49    if tag_number < 0 {
50        Err(tonic::Status::internal(format!(
51            "Invalid protocol version: {tag_number}"
52        )))
53    } else {
54        Ok(ProtocolVersionInt(tag_number as u64 + 1))
55    }
56}
57
58impl TryFrom<AccountAddress> for super::AccountAddress {
59    type Error = tonic::Status;
60
61    fn try_from(value: AccountAddress) -> Result<Self, Self::Error> {
62        match value.value.try_into() {
63            Ok(addr) => Ok(Self(addr)),
64            Err(_) => Err(tonic::Status::internal(
65                "Unexpected account address format.",
66            )),
67        }
68    }
69}
70
71impl From<super::ContractAddress> for ContractAddress {
72    fn from(value: super::ContractAddress) -> Self {
73        Self {
74            index: value.index,
75            subindex: value.subindex,
76        }
77    }
78}
79
80impl TryFrom<Address> for super::types::Address {
81    type Error = tonic::Status;
82
83    fn try_from(value: Address) -> Result<Self, Self::Error> {
84        match value.r#type.require()? {
85            address::Type::Account(acc) => Ok(Self::Account(acc.try_into()?)),
86            address::Type::Contract(contr) => Ok(Self::Contract(contr.into())),
87        }
88    }
89}
90
91impl TryFrom<ModuleRef> for super::ModuleReference {
92    type Error = tonic::Status;
93
94    fn try_from(value: ModuleRef) -> Result<Self, Self::Error> {
95        match value.value.try_into() {
96            Ok(mod_ref) => Ok(Self::new(mod_ref)),
97            Err(_) => Err(tonic::Status::internal(
98                "Unexpected module reference format.",
99            )),
100        }
101    }
102}
103
104impl From<ContractAddress> for super::ContractAddress {
105    fn from(value: ContractAddress) -> Self {
106        super::ContractAddress::new(value.index, value.subindex)
107    }
108}
109
110impl From<Slot> for super::types::Slot {
111    fn from(value: Slot) -> Self {
112        super::types::Slot { slot: value.value }
113    }
114}
115
116impl TryFrom<VersionedModuleSource> for super::types::smart_contracts::WasmModule {
117    type Error = tonic::Status;
118
119    fn try_from(versioned_module: VersionedModuleSource) -> Result<Self, Self::Error> {
120        use super::types::smart_contracts::WasmVersion;
121        let module = match versioned_module.module.require()? {
122            versioned_module_source::Module::V0(versioned_module_source::ModuleSourceV0 {
123                value,
124            }) => super::types::smart_contracts::WasmModule {
125                version: WasmVersion::V0,
126                source: value.into(),
127            },
128            versioned_module_source::Module::V1(versioned_module_source::ModuleSourceV1 {
129                value,
130            }) => super::types::smart_contracts::WasmModule {
131                version: WasmVersion::V1,
132                source: value.into(),
133            },
134        };
135        Ok(module)
136    }
137}
138
139impl TryFrom<Parameter> for super::types::smart_contracts::OwnedParameter {
140    type Error = tonic::Status;
141
142    fn try_from(value: Parameter) -> Result<Self, Self::Error> {
143        Self::try_from(value.value).map_err(
144            |e: concordium_base::smart_contracts::ExceedsParameterSize| {
145                tonic::Status::invalid_argument(e.to_string())
146            },
147        )
148    }
149}
150
151impl TryFrom<InstanceInfo> for super::InstanceInfo {
152    type Error = tonic::Status;
153
154    fn try_from(value: InstanceInfo) -> Result<Self, Self::Error> {
155        match value.version.require()? {
156            instance_info::Version::V0(v0) => Ok(Self::V0 {
157                model: v0.model.require()?.value,
158                owner: v0.owner.require()?.try_into()?,
159                amount: v0.amount.require()?.into(),
160                methods: v0
161                    .methods
162                    .into_iter()
163                    .map(TryFrom::try_from)
164                    .collect::<Result<_, tonic::Status>>()?,
165                name: v0.name.require()?.try_into()?,
166                source_module: v0.source_module.require()?.try_into()?,
167            }),
168            instance_info::Version::V1(v1) => Ok(Self::V1 {
169                owner: v1.owner.require()?.try_into()?,
170                amount: v1.amount.require()?.into(),
171                methods: v1
172                    .methods
173                    .into_iter()
174                    .map(TryFrom::try_from)
175                    .collect::<Result<_, tonic::Status>>()?,
176                name: v1.name.require()?.try_into()?,
177                source_module: v1.source_module.require()?.try_into()?,
178            }),
179        }
180    }
181}
182
183impl TryFrom<ReceiveName> for concordium_base::contracts_common::OwnedReceiveName {
184    type Error = tonic::Status;
185
186    fn try_from(value: ReceiveName) -> Result<Self, Self::Error> {
187        match Self::new(value.value) {
188            Ok(rn) => Ok(rn),
189            Err(_) => Err(tonic::Status::internal("Unexpected receive name format.")),
190        }
191    }
192}
193
194impl TryFrom<InitName> for concordium_base::contracts_common::OwnedContractName {
195    type Error = tonic::Status;
196
197    fn try_from(value: InitName) -> Result<Self, Self::Error> {
198        match Self::new(value.value) {
199            Ok(cn) => Ok(cn),
200            Err(_) => Err(tonic::Status::internal("Unexpected contract name format.")),
201        }
202    }
203}
204
205impl TryFrom<BlockHash> for super::BlockHash {
206    type Error = tonic::Status;
207
208    fn try_from(value: BlockHash) -> Result<Self, Self::Error> {
209        match value.value.try_into() {
210            Ok(hash) => Ok(Self::new(hash)),
211            Err(_) => Err(tonic::Status::internal("Unexpected block hash format.")),
212        }
213    }
214}
215
216impl TryFrom<TransactionHash> for super::hashes::TransactionHash {
217    type Error = tonic::Status;
218
219    fn try_from(value: TransactionHash) -> Result<Self, Self::Error> {
220        match value.value.try_into() {
221            Ok(hash) => Ok(Self::new(hash)),
222            Err(_) => Err(tonic::Status::internal(
223                "Unexpected transaction hash format.",
224            )),
225        }
226    }
227}
228
229impl TryFrom<AccountTransactionSignHash> for super::hashes::TransactionSignHash {
230    type Error = tonic::Status;
231
232    fn try_from(value: AccountTransactionSignHash) -> Result<Self, Self::Error> {
233        match value.value.try_into() {
234            Ok(hash) => Ok(Self::new(hash)),
235            Err(_) => Err(tonic::Status::internal(
236                "Unexpected account transaction sign hash format.",
237            )),
238        }
239    }
240}
241
242impl TryFrom<Sha256Hash> for super::hashes::Hash {
243    type Error = tonic::Status;
244
245    fn try_from(value: Sha256Hash) -> Result<Self, Self::Error> {
246        match value.value.try_into() {
247            Ok(hash) => Ok(Self::new(hash)),
248            Err(_) => Err(tonic::Status::internal("Unexpected hash format.")),
249        }
250    }
251}
252
253impl TryFrom<StateHash> for super::hashes::StateHash {
254    type Error = tonic::Status;
255
256    fn try_from(value: StateHash) -> Result<Self, Self::Error> {
257        match value.value.try_into() {
258            Ok(hash) => Ok(Self::new(hash)),
259            Err(_) => Err(tonic::Status::internal("Unexpected state hash format.")),
260        }
261    }
262}
263
264impl TryFrom<LeadershipElectionNonce> for super::hashes::LeadershipElectionNonce {
265    type Error = tonic::Status;
266
267    fn try_from(value: LeadershipElectionNonce) -> Result<Self, Self::Error> {
268        match value.value.try_into() {
269            Ok(hash) => Ok(Self::new(hash)),
270            Err(_) => Err(tonic::Status::internal(
271                "Unexpected leadership election nonce format.",
272            )),
273        }
274    }
275}
276
277impl From<AbsoluteBlockHeight> for super::AbsoluteBlockHeight {
278    fn from(abh: AbsoluteBlockHeight) -> Self {
279        Self { height: abh.value }
280    }
281}
282
283impl From<BlockHeight> for super::types::BlockHeight {
284    fn from(bh: BlockHeight) -> Self {
285        Self { height: bh.value }
286    }
287}
288
289impl From<super::AbsoluteBlockHeight> for AbsoluteBlockHeight {
290    fn from(abh: super::AbsoluteBlockHeight) -> Self {
291        Self { value: abh.height }
292    }
293}
294
295impl From<super::RelativeBlockHeight> for block_hash_input::RelativeHeight {
296    fn from(relative_block_height: super::RelativeBlockHeight) -> Self {
297        Self {
298            genesis_index: Some(relative_block_height.genesis_index.into()),
299            height: Some(relative_block_height.height.into()),
300            restrict: relative_block_height.restrict,
301        }
302    }
303}
304
305impl From<super::types::BlockHeight> for BlockHeight {
306    fn from(bh: super::types::BlockHeight) -> Self {
307        Self { value: bh.height }
308    }
309}
310
311impl From<SequenceNumber> for super::types::Nonce {
312    fn from(n: SequenceNumber) -> Self {
313        Self { nonce: n.value }
314    }
315}
316
317impl From<Amount> for super::super::common::types::Amount {
318    fn from(n: Amount) -> Self {
319        Self { micro_ccd: n.value }
320    }
321}
322
323impl From<AccountIndex> for super::types::AccountIndex {
324    fn from(n: AccountIndex) -> Self {
325        Self { index: n.value }
326    }
327}
328
329impl From<super::types::AccountIndex> for AccountIndex {
330    fn from(n: super::types::AccountIndex) -> Self {
331        Self { value: n.index }
332    }
333}
334
335impl From<BakerId> for super::types::BakerId {
336    fn from(n: BakerId) -> Self {
337        Self { id: n.value.into() }
338    }
339}
340
341impl From<super::types::BakerId> for BakerId {
342    fn from(n: super::types::BakerId) -> Self {
343        Self { value: n.id.into() }
344    }
345}
346
347impl TryFrom<DelegationTarget> for super::types::DelegationTarget {
348    type Error = tonic::Status;
349
350    fn try_from(dt: DelegationTarget) -> Result<Self, Self::Error> {
351        match dt.target.require()? {
352            delegation_target::Target::Passive(_) => Ok(Self::Passive),
353            delegation_target::Target::Baker(bid) => Ok(Self::Baker {
354                baker_id: bid.into(),
355            }),
356        }
357    }
358}
359
360impl TryFrom<EncryptionKey> for crate::id::elgamal::PublicKey<ArCurve> {
361    type Error = tonic::Status;
362
363    fn try_from(value: EncryptionKey) -> Result<Self, Self::Error> {
364        consume(&value.value)
365    }
366}
367
368impl TryFrom<ar_info::ArPublicKey> for crate::id::elgamal::PublicKey<ArCurve> {
369    type Error = tonic::Status;
370
371    fn try_from(value: ar_info::ArPublicKey) -> Result<Self, Self::Error> {
372        consume(&value.value)
373    }
374}
375
376impl TryFrom<AccountThreshold> for super::types::AccountThreshold {
377    type Error = tonic::Status;
378
379    fn try_from(value: AccountThreshold) -> Result<Self, Self::Error> {
380        if let Ok(Ok(v)) = u8::try_from(value.value).map(Self::try_from) {
381            Ok(v)
382        } else {
383            Err(tonic::Status::internal("Unexpected account threshold."))
384        }
385    }
386}
387
388impl TryFrom<EncryptedAmount> for crate::encrypted_transfers::types::EncryptedAmount<ArCurve> {
389    type Error = tonic::Status;
390
391    fn try_from(value: EncryptedAmount) -> Result<Self, Self::Error> {
392        consume(&value.value)
393    }
394}
395
396impl TryFrom<BakerElectionVerifyKey> for super::types::BakerElectionVerifyKey {
397    type Error = tonic::Status;
398
399    fn try_from(value: BakerElectionVerifyKey) -> Result<Self, Self::Error> {
400        consume(&value.value)
401    }
402}
403
404impl TryFrom<BakerSignatureVerifyKey> for super::types::BakerSignatureVerifyKey {
405    type Error = tonic::Status;
406
407    fn try_from(value: BakerSignatureVerifyKey) -> Result<Self, Self::Error> {
408        consume(&value.value)
409    }
410}
411
412impl TryFrom<BakerAggregationVerifyKey> for super::types::BakerAggregationVerifyKey {
413    type Error = tonic::Status;
414
415    fn try_from(value: BakerAggregationVerifyKey) -> Result<Self, Self::Error> {
416        consume(&value.value)
417    }
418}
419
420impl TryFrom<EncryptedBalance> for super::types::AccountEncryptedAmount {
421    type Error = tonic::Status;
422
423    fn try_from(value: EncryptedBalance) -> Result<Self, Self::Error> {
424        let self_amount = value.self_amount.require()?.try_into()?;
425        let start_index = value.start_index;
426        let aggregated_amount = match (value.aggregated_amount, value.num_aggregated) {
427            (Some(aa), Some(si)) => Some((aa.try_into()?, si)),
428            (None, None) => None,
429            _ => {
430                return Err(tonic::Status::internal(
431                    "Unexpected response for 'EncryptedBalance'.",
432                ))
433            }
434        };
435        let incoming_amounts = value
436            .incoming_amounts
437            .into_iter()
438            .map(TryFrom::try_from)
439            .collect::<Result<_, tonic::Status>>()?;
440        Ok(Self {
441            self_amount,
442            start_index,
443            aggregated_amount,
444            incoming_amounts,
445        })
446    }
447}
448
449impl TryFrom<Duration> for chrono::Duration {
450    type Error = tonic::Status;
451
452    fn try_from(value: Duration) -> Result<Self, Self::Error> {
453        chrono::TimeDelta::try_milliseconds(value.value as i64).ok_or_else(|| {
454            tonic::Status::internal("Unexpected response for 'Duration': Duration out of bounds.")
455        })
456    }
457}
458
459impl From<Duration> for super::types::SlotDuration {
460    fn from(value: Duration) -> Self {
461        super::types::SlotDuration {
462            millis: value.value,
463        }
464    }
465}
466
467impl From<Duration> for concordium_base::contracts_common::Duration {
468    fn from(value: Duration) -> Self {
469        concordium_base::contracts_common::Duration::from_millis(value.value)
470    }
471}
472
473impl From<GenesisIndex> for super::types::GenesisIndex {
474    fn from(value: GenesisIndex) -> Self {
475        value.value.into()
476    }
477}
478
479impl From<super::types::GenesisIndex> for GenesisIndex {
480    fn from(value: super::types::GenesisIndex) -> Self {
481        GenesisIndex {
482            value: value.into(),
483        }
484    }
485}
486
487impl From<ProtocolVersion> for super::types::ProtocolVersion {
488    fn from(value: ProtocolVersion) -> Self {
489        match value {
490            ProtocolVersion::ProtocolVersion1 => super::types::ProtocolVersion::P1,
491            ProtocolVersion::ProtocolVersion2 => super::types::ProtocolVersion::P2,
492            ProtocolVersion::ProtocolVersion3 => super::types::ProtocolVersion::P3,
493            ProtocolVersion::ProtocolVersion4 => super::types::ProtocolVersion::P4,
494            ProtocolVersion::ProtocolVersion5 => super::types::ProtocolVersion::P5,
495            ProtocolVersion::ProtocolVersion6 => super::types::ProtocolVersion::P6,
496            ProtocolVersion::ProtocolVersion7 => super::types::ProtocolVersion::P7,
497            ProtocolVersion::ProtocolVersion8 => super::types::ProtocolVersion::P8,
498            ProtocolVersion::ProtocolVersion9 => super::types::ProtocolVersion::P9,
499        }
500    }
501}
502
503impl From<super::types::ProtocolVersion> for ProtocolVersion {
504    fn from(value: super::types::ProtocolVersion) -> Self {
505        match value {
506            super::types::ProtocolVersion::P1 => ProtocolVersion::ProtocolVersion1,
507            super::types::ProtocolVersion::P2 => ProtocolVersion::ProtocolVersion2,
508            super::types::ProtocolVersion::P3 => ProtocolVersion::ProtocolVersion3,
509            super::types::ProtocolVersion::P4 => ProtocolVersion::ProtocolVersion4,
510            super::types::ProtocolVersion::P5 => ProtocolVersion::ProtocolVersion5,
511            super::types::ProtocolVersion::P6 => ProtocolVersion::ProtocolVersion6,
512            super::types::ProtocolVersion::P7 => ProtocolVersion::ProtocolVersion7,
513            super::types::ProtocolVersion::P8 => ProtocolVersion::ProtocolVersion8,
514            super::types::ProtocolVersion::P9 => ProtocolVersion::ProtocolVersion9,
515        }
516    }
517}
518
519impl TryFrom<StakePendingChange> for super::types::StakePendingChange {
520    type Error = tonic::Status;
521
522    fn try_from(value: StakePendingChange) -> Result<Self, Self::Error> {
523        match value.change.require()? {
524            stake_pending_change::Change::Reduce(rs) => Ok(Self::ReduceStake {
525                new_stake: rs.new_stake.require()?.into(),
526                effective_time: rs.effective_time.require()?.try_into()?,
527            }),
528            stake_pending_change::Change::Remove(rs) => {
529                let effective_time = rs.try_into()?;
530                Ok(Self::RemoveStake { effective_time })
531            }
532        }
533    }
534}
535
536impl TryFrom<BakerInfo> for super::types::BakerInfo {
537    type Error = tonic::Status;
538
539    fn try_from(value: BakerInfo) -> Result<Self, Self::Error> {
540        Ok(Self {
541            baker_id: value.baker_id.require()?.into(),
542            baker_election_verify_key: value.election_key.require()?.try_into()?,
543            baker_signature_verify_key: value.signature_key.require()?.try_into()?,
544            baker_aggregation_verify_key: value.aggregation_key.require()?.try_into()?,
545        })
546    }
547}
548
549impl From<OpenStatus> for super::types::OpenStatus {
550    fn from(os: OpenStatus) -> Self {
551        match os {
552            OpenStatus::OpenForAll => Self::OpenForAll,
553            OpenStatus::ClosedForNew => Self::ClosedForNew,
554            OpenStatus::ClosedForAll => Self::ClosedForAll,
555        }
556    }
557}
558
559impl From<AmountFraction> for super::types::AmountFraction {
560    fn from(af: AmountFraction) -> Self {
561        Self::new_unchecked(af.parts_per_hundred_thousand)
562    }
563}
564
565impl From<AmountFraction> for super::types::PartsPerHundredThousands {
566    fn from(af: AmountFraction) -> Self {
567        Self::new_unchecked(af.parts_per_hundred_thousand)
568    }
569}
570
571impl TryFrom<CommissionRates> for super::types::CommissionRates {
572    type Error = tonic::Status;
573
574    fn try_from(value: CommissionRates) -> Result<Self, Self::Error> {
575        Ok(Self {
576            finalization: value.finalization.require()?.into(),
577            baking: value.baking.require()?.into(),
578            transaction: value.transaction.require()?.into(),
579        })
580    }
581}
582
583impl TryFrom<BakerPoolInfo> for super::types::BakerPoolInfo {
584    type Error = tonic::Status;
585
586    fn try_from(value: BakerPoolInfo) -> Result<Self, Self::Error> {
587        let open_status = Upward::from(OpenStatus::try_from(value.open_status).ok())
588            .map(super::types::OpenStatus::from);
589        let metadata_url = value
590            .url
591            .try_into()
592            .map_err(|_| tonic::Status::internal("Unexpected metadata length."))?;
593        let commission_rates = value.commission_rates.require()?.try_into()?;
594        Ok(Self {
595            open_status,
596            metadata_url,
597            commission_rates,
598        })
599    }
600}
601
602impl TryFrom<account_staking_info::StakingInfo> for super::types::AccountStakingInfo {
603    type Error = tonic::Status;
604
605    fn try_from(value: account_staking_info::StakingInfo) -> Result<Self, Self::Error> {
606        match value {
607            account_staking_info::StakingInfo::Baker(bsi) => {
608                let staked_amount = bsi.staked_amount.require()?.into();
609                let restake_earnings = bsi.restake_earnings;
610                let baker_info = bsi.baker_info.require()?.try_into()?;
611                let pending_change = match bsi.pending_change {
612                    None => None,
613                    Some(pc) => Some(pc.try_into()?),
614                };
615                let pool_info = match bsi.pool_info {
616                    None => None,
617                    Some(bi) => Some(bi.try_into()?),
618                };
619                let is_suspended = bsi.is_suspended;
620                Ok(Self::Baker {
621                    staked_amount,
622                    restake_earnings,
623                    baker_info: Box::new(baker_info),
624                    pending_change,
625                    pool_info,
626                    is_suspended,
627                })
628            }
629            account_staking_info::StakingInfo::Delegator(dsi) => {
630                let staked_amount = dsi.staked_amount.require()?.into();
631                let restake_earnings = dsi.restake_earnings;
632                let delegation_target = dsi.target.require()?.try_into()?;
633                let pending_change = match dsi.pending_change {
634                    None => None,
635                    Some(pc) => Some(pc.try_into()?),
636                };
637                Ok(Self::Delegated {
638                    staked_amount,
639                    restake_earnings,
640                    delegation_target,
641                    pending_change,
642                })
643            }
644        }
645    }
646}
647
648impl TryFrom<Release> for super::types::Release {
649    type Error = tonic::Status;
650
651    fn try_from(value: Release) -> Result<Self, Self::Error> {
652        Ok(Self {
653            timestamp: value.timestamp.require()?.try_into()?,
654            amount: value.amount.require()?.into(),
655            transactions: value
656                .transactions
657                .into_iter()
658                .map(TryFrom::try_from)
659                .collect::<Result<_, tonic::Status>>()?,
660        })
661    }
662}
663
664impl TryFrom<ReleaseSchedule> for super::types::AccountReleaseSchedule {
665    type Error = tonic::Status;
666
667    fn try_from(value: ReleaseSchedule) -> Result<Self, Self::Error> {
668        Ok(Self {
669            total: value.total.require()?.into(),
670            schedule: value
671                .schedules
672                .into_iter()
673                .map(TryFrom::try_from)
674                .collect::<Result<_, tonic::Status>>()?,
675        })
676    }
677}
678
679impl TryFrom<AccountVerifyKey> for Upward<crate::id::types::VerifyKey> {
680    type Error = tonic::Status;
681
682    fn try_from(value: AccountVerifyKey) -> Result<Self, Self::Error> {
683        let Some(key) = value.key else {
684            return Ok(Upward::Unknown(()));
685        };
686        match key {
687            account_verify_key::Key::Ed25519Key(v) => Ok(Upward::Known(
688                crate::id::types::VerifyKey::Ed25519VerifyKey(consume(&v)?),
689            )),
690        }
691    }
692}
693
694impl TryFrom<ip_info::IpCdiVerifyKey> for ed25519_dalek::VerifyingKey {
695    type Error = tonic::Status;
696
697    fn try_from(value: ip_info::IpCdiVerifyKey) -> Result<Self, Self::Error> {
698        consume(&value.value)
699    }
700}
701
702impl TryFrom<ip_info::IpVerifyKey> for crate::id::ps_sig::PublicKey<IpPairing> {
703    type Error = tonic::Status;
704
705    fn try_from(value: ip_info::IpVerifyKey) -> Result<Self, Self::Error> {
706        consume(&value.value)
707    }
708}
709
710impl TryFrom<UpdatePublicKey> for super::types::UpdatePublicKey {
711    type Error = tonic::Status;
712
713    fn try_from(value: UpdatePublicKey) -> Result<Self, Self::Error> {
714        Ok(super::types::UpdatePublicKey {
715            public: crate::id::types::VerifyKey::Ed25519VerifyKey(consume(&value.value)?),
716        })
717    }
718}
719
720impl TryFrom<SignatureThreshold> for crate::id::types::SignatureThreshold {
721    type Error = tonic::Status;
722
723    fn try_from(value: SignatureThreshold) -> Result<Self, Self::Error> {
724        if let Ok(v) = u8::try_from(value.value) {
725            crate::id::types::SignatureThreshold::try_from(v)
726                .map_err(|_| tonic::Status::internal("Unexpected zero signature threshold."))
727        } else {
728            Err(tonic::Status::internal("Unexpected signature threshold."))
729        }
730    }
731}
732
733impl TryFrom<ArThreshold> for crate::id::secret_sharing::Threshold {
734    type Error = tonic::Status;
735
736    fn try_from(value: ArThreshold) -> Result<Self, Self::Error> {
737        if let Ok(v) = u8::try_from(value.value) {
738            if v == 0 {
739                Err(tonic::Status::internal("Unexpected zero AR threshold."))
740            } else {
741                Ok(Self(v))
742            }
743        } else {
744            Err(tonic::Status::internal("Unexpected AR threshold."))
745        }
746    }
747}
748
749impl TryFrom<CredentialPublicKeys> for Upward<crate::id::types::CredentialPublicKeys> {
750    type Error = tonic::Status;
751
752    fn try_from(value: CredentialPublicKeys) -> Result<Self, Self::Error> {
753        let mut keys = BTreeMap::new();
754        for (index, key) in value.keys {
755            let k = u8::try_from(index)
756                .map_err(|_| tonic::Status::internal("Unexpected key index."))?
757                .into();
758
759            let Upward::Known(v) = key.try_into()? else {
760                return Ok(Upward::Unknown(()));
761            };
762            keys.insert(k, v);
763        }
764        Ok(Upward::Known(crate::id::types::CredentialPublicKeys {
765            keys,
766            threshold: value.threshold.require()?.try_into()?,
767        }))
768    }
769}
770
771impl TryFrom<CredentialRegistrationId> for super::types::CredentialRegistrationID {
772    type Error = tonic::Status;
773
774    fn try_from(value: CredentialRegistrationId) -> Result<Self, Self::Error> {
775        consume(&value.value)
776    }
777}
778
779impl TryFrom<CredentialRegistrationId> for ArCurve {
780    type Error = tonic::Status;
781
782    fn try_from(value: CredentialRegistrationId) -> Result<Self, Self::Error> {
783        consume(&value.value)
784    }
785}
786
787impl From<IdentityProviderIdentity> for crate::id::types::IpIdentity {
788    fn from(v: IdentityProviderIdentity) -> Self {
789        Self(v.value)
790    }
791}
792
793impl TryFrom<YearMonth> for crate::id::types::YearMonth {
794    type Error = tonic::Status;
795
796    fn try_from(value: YearMonth) -> Result<Self, Self::Error> {
797        Ok(Self {
798            year: value
799                .year
800                .try_into()
801                .map_err(|_| tonic::Status::internal("Unexpected year."))?,
802            month: value
803                .month
804                .try_into()
805                .map_err(|_| tonic::Status::internal("Unexpected year."))?,
806        })
807    }
808}
809
810impl TryFrom<Policy> for crate::id::types::Policy<ArCurve, AttributeKind> {
811    type Error = tonic::Status;
812
813    fn try_from(value: Policy) -> Result<Self, Self::Error> {
814        Ok(Self {
815            valid_to: value.valid_to.require()?.try_into()?,
816            created_at: value.created_at.require()?.try_into()?,
817            policy_vec: value
818                .attributes
819                .into_iter()
820                .map(|(k, v)| {
821                    let k = crate::id::types::AttributeTag(
822                        k.try_into()
823                            .map_err(|_| tonic::Status::internal("Unexpected attribute tag."))?,
824                    );
825                    let v = AttributeKind::try_new(String::from_utf8(v).map_err(|_| {
826                        tonic::Status::internal("Invalid attribute value. Expected UTF8 encoding")
827                    })?)
828                    .map_err(|_| tonic::Status::internal("Attribute value too long."))?;
829                    Ok((k, v))
830                })
831                .collect::<Result<_, tonic::Status>>()?,
832            _phantom: std::marker::PhantomData,
833        })
834    }
835}
836
837impl TryFrom<ChainArData> for crate::id::types::ChainArData<ArCurve> {
838    type Error = tonic::Status;
839
840    fn try_from(value: ChainArData) -> Result<Self, Self::Error> {
841        consume(&value.enc_id_cred_pub_share)
842    }
843}
844
845impl TryFrom<Commitment> for crate::id::pedersen_commitment::Commitment<ArCurve> {
846    type Error = tonic::Status;
847
848    fn try_from(value: Commitment) -> Result<Self, Self::Error> {
849        consume(&value.value)
850    }
851}
852
853impl TryFrom<CredentialCommitments> for crate::id::types::CredentialDeploymentCommitments<ArCurve> {
854    type Error = tonic::Status;
855
856    fn try_from(value: CredentialCommitments) -> Result<Self, Self::Error> {
857        Ok(Self {
858            cmm_prf: value.prf.require()?.try_into()?,
859            cmm_cred_counter: value.cred_counter.require()?.try_into()?,
860            cmm_max_accounts: value.max_accounts.require()?.try_into()?,
861            cmm_attributes: value
862                .attributes
863                .into_iter()
864                .map(|(k, v)| {
865                    let k = crate::id::types::AttributeTag(
866                        k.try_into()
867                            .map_err(|_| tonic::Status::internal("Unexpected attribute tag."))?,
868                    );
869                    let v = v.try_into()?;
870                    Ok((k, v))
871                })
872                .collect::<Result<_, tonic::Status>>()?,
873            cmm_id_cred_sec_sharing_coeff: value
874                .id_cred_sec_sharing_coeff
875                .into_iter()
876                .map(TryFrom::try_from)
877                .collect::<Result<_, tonic::Status>>()?,
878        })
879    }
880}
881
882impl TryFrom<AccountCredential> for Upward<AccountCredentialWithoutProofs<ArCurve, AttributeKind>> {
883    type Error = tonic::Status;
884
885    fn try_from(message: AccountCredential) -> Result<Self, Self::Error> {
886        let Some(values) = message.credential_values else {
887            return Ok(Upward::Unknown(()));
888        };
889        values.try_into()
890    }
891}
892
893impl TryFrom<account_credential::CredentialValues>
894    for Upward<AccountCredentialWithoutProofs<ArCurve, AttributeKind>>
895{
896    type Error = tonic::Status;
897
898    fn try_from(cred: account_credential::CredentialValues) -> Result<Self, Self::Error> {
899        match cred {
900            account_credential::CredentialValues::Initial(ic) => {
901                let Upward::Known(cred_account) = ic.keys.require()?.try_into()? else {
902                    return Ok(Upward::Unknown(()));
903                };
904                let icdv = InitialCredentialDeploymentValues {
905                    cred_account,
906                    reg_id: ic.cred_id.require()?.try_into()?,
907                    ip_identity: ic.ip_id.require()?.into(),
908                    policy: ic.policy.require()?.try_into()?,
909                };
910                Ok(Upward::Known(AccountCredentialWithoutProofs::Initial {
911                    icdv,
912                }))
913            }
914            account_credential::CredentialValues::Normal(nc) => {
915                let Upward::Known(cred_key_info) = nc.keys.require()?.try_into()? else {
916                    return Ok(Upward::Unknown(()));
917                };
918
919                let cdv = CredentialDeploymentValues {
920                    cred_key_info,
921                    cred_id: nc.cred_id.require()?.try_into()?,
922                    ip_identity: nc.ip_id.require()?.into(),
923                    threshold: nc.ar_threshold.require()?.try_into()?,
924                    ar_data: nc
925                        .ar_data
926                        .into_iter()
927                        .map(|(k, v)| {
928                            let k = k
929                                .try_into()
930                                .map_err(|_| tonic::Status::internal("Unexpected AR identity."))?;
931                            let v = v.try_into()?;
932                            Ok((k, v))
933                        })
934                        .collect::<Result<_, tonic::Status>>()?,
935                    policy: nc.policy.require()?.try_into()?,
936                };
937                let commitments = nc.commitments.require()?.try_into()?;
938                Ok(Upward::Known(AccountCredentialWithoutProofs::Normal {
939                    cdv,
940                    commitments,
941                }))
942            }
943        }
944    }
945}
946
947impl From<Timestamp> for concordium_base::common::types::Timestamp {
948    fn from(value: Timestamp) -> Self {
949        value.value.into()
950    }
951}
952
953impl From<concordium_base::common::types::Timestamp> for Timestamp {
954    fn from(value: concordium_base::common::types::Timestamp) -> Self {
955        Timestamp {
956            value: value.millis,
957        }
958    }
959}
960
961impl TryFrom<Timestamp> for chrono::DateTime<chrono::Utc> {
962    type Error = tonic::Status;
963
964    fn try_from(value: Timestamp) -> Result<Self, Self::Error> {
965        let ts = chrono::Utc.timestamp_millis_opt(
966            value
967                .value
968                .try_into()
969                .map_err(|_| tonic::Status::internal("Timestamp out of range."))?,
970        );
971        ts.single()
972            .ok_or_else(|| tonic::Status::internal("Ambiguous time."))
973    }
974}
975
976impl TryFrom<DelegatorInfo> for super::types::DelegatorInfo {
977    type Error = tonic::Status;
978
979    fn try_from(delegator: DelegatorInfo) -> Result<Self, Self::Error> {
980        Ok(Self {
981            account: delegator.account.require()?.try_into()?,
982            stake: delegator.stake.require()?.into(),
983            pending_change: delegator
984                .pending_change
985                .map(TryFrom::try_from)
986                .transpose()?,
987        })
988    }
989}
990
991impl TryFrom<DelegatorRewardPeriodInfo> for super::types::DelegatorRewardPeriodInfo {
992    type Error = tonic::Status;
993
994    fn try_from(delegator: DelegatorRewardPeriodInfo) -> Result<Self, Self::Error> {
995        Ok(Self {
996            account: delegator.account.require()?.try_into()?,
997            stake: delegator.stake.require()?.into(),
998        })
999    }
1000}
1001
1002impl From<CooldownStatus> for super::types::CooldownStatus {
1003    fn from(cds: CooldownStatus) -> Self {
1004        match cds {
1005            CooldownStatus::Cooldown => Self::Cooldown,
1006            CooldownStatus::PreCooldown => Self::PreCooldown,
1007            CooldownStatus::PrePreCooldown => Self::PrePreCooldown,
1008        }
1009    }
1010}
1011
1012impl TryFrom<Cooldown> for super::types::Cooldown {
1013    type Error = tonic::Status;
1014
1015    fn try_from(cd: Cooldown) -> Result<Self, Self::Error> {
1016        Ok(Self {
1017            status: Upward::from(CooldownStatus::try_from(cd.status).ok())
1018                .map(super::types::CooldownStatus::from),
1019            end_time: cd.end_time.require()?.into(),
1020            amount: cd.amount.require()?.into(),
1021        })
1022    }
1023}
1024
1025impl TryFrom<AccountInfo> for super::types::AccountInfo {
1026    type Error = tonic::Status;
1027
1028    fn try_from(value: AccountInfo) -> Result<Self, Self::Error> {
1029        let AccountInfo {
1030            sequence_number,
1031            amount,
1032            schedule,
1033            creds,
1034            threshold,
1035            encrypted_balance,
1036            encryption_key,
1037            index,
1038            stake,
1039            address,
1040            cooldowns,
1041            available_balance,
1042            tokens,
1043        } = value;
1044        let account_nonce = sequence_number.require()?.into();
1045        let account_amount = amount.require()?.into();
1046        let account_release_schedule: AccountReleaseSchedule = schedule.require()?.try_into()?;
1047        let account_threshold = threshold.require()?.try_into()?;
1048        let account_encrypted_amount = encrypted_balance.require()?.try_into()?;
1049        let account_encryption_key = encryption_key.require()?.try_into()?;
1050        let account_index = index.require()?.into();
1051        let account_stake: Option<Upward<super::types::AccountStakingInfo>> = match stake {
1052            Some(stake) => Some(Upward::from(
1053                stake.staking_info.map(TryInto::try_into).transpose()?,
1054            )),
1055            None => None,
1056        };
1057        let account_address = address.require()?.try_into()?;
1058        let mut cds: Vec<super::types::Cooldown> = Vec::with_capacity(cooldowns.len());
1059        for cooldown in cooldowns.into_iter() {
1060            cds.push(cooldown.try_into()?)
1061        }
1062        let cooldowns = cds;
1063
1064        // The available balance is only provided as convenience and in case the
1065        // calculation of it changes in the future. It should be present if the node
1066        // is version 7 (or later). If the available balance is not present,
1067        // we calculate it manually instead.
1068        // If we up the minimum supported node version to version 7, we can remove this
1069        // fallback calculation and instead require the available balance field to
1070        // always be present.
1071        let available_balance = available_balance.map(|ab| ab.into()).unwrap_or_else(|| {
1072            let active_stake = if let Some(Upward::Known(staking_info)) = &account_stake {
1073                staking_info.staked_amount()
1074            } else {
1075                Default::default()
1076            };
1077
1078            let inactive_stake = cooldowns.iter().map(|cd| cd.amount).sum();
1079
1080            let staked_amount = active_stake + inactive_stake;
1081
1082            // The locked amount is the maximum of the amount in the release schedule and
1083            // the total amount that is actively staked or in cooldown (inactive stake).
1084            let locked_amount = Ord::max(account_release_schedule.total, staked_amount);
1085
1086            // According to the protobuf documentation:
1087            // The available (unencrypted) balance of the account is the balance minus the
1088            // locked amount.
1089            account_amount - locked_amount
1090        });
1091
1092        let tokens = tokens
1093            .into_iter()
1094            .map(|token| token.try_into())
1095            .collect::<Result<_, _>>()?;
1096        Ok(Self {
1097            account_nonce,
1098            account_amount,
1099            account_release_schedule,
1100            account_credentials: creds
1101                .into_iter()
1102                .map(|(k, v)| {
1103                    let k = u8::try_from(k)
1104                        .map_err(|_| tonic::Status::internal("Unexpected credential index."))?
1105                        .into();
1106                    let v = v.try_into()?;
1107                    Ok((k, Versioned::new(VERSION_0, v)))
1108                })
1109                .collect::<Result<_, tonic::Status>>()?,
1110            account_threshold,
1111            account_encrypted_amount,
1112            account_encryption_key,
1113            account_index,
1114            account_stake,
1115            account_address,
1116            cooldowns,
1117            available_balance,
1118            tokens,
1119        })
1120    }
1121}
1122
1123impl TryFrom<BlockItemStatus> for super::types::TransactionStatus {
1124    type Error = tonic::Status;
1125
1126    fn try_from(value: BlockItemStatus) -> Result<Self, Self::Error> {
1127        match value.status.require()? {
1128            block_item_status::Status::Received(_) => Ok(super::types::TransactionStatus::Received),
1129            block_item_status::Status::Finalized(f) => {
1130                let mut summaries: BTreeMap<super::BlockHash, super::types::BlockItemSummary> =
1131                    BTreeMap::new();
1132                let o = f.outcome.require()?;
1133                let k = o.block_hash.require()?.try_into()?;
1134                let v = o.outcome.require()?.try_into()?;
1135                summaries.insert(k, v);
1136                Ok(super::types::TransactionStatus::Finalized(summaries))
1137            }
1138            block_item_status::Status::Committed(cs) => {
1139                let mut summaries: BTreeMap<super::BlockHash, super::types::BlockItemSummary> =
1140                    BTreeMap::new();
1141                for o in cs.outcomes {
1142                    let k = o.block_hash.require()?.try_into()?;
1143                    let v = o.outcome.require()?.try_into()?;
1144                    summaries.insert(k, v);
1145                }
1146                Ok(super::types::TransactionStatus::Committed(summaries))
1147            }
1148        }
1149    }
1150}
1151
1152impl TryFrom<AccountTransactionPayload> for concordium_base::transactions::EncodedPayload {
1153    type Error = tonic::Status;
1154
1155    fn try_from(value: AccountTransactionPayload) -> Result<Self, Self::Error> {
1156        use concordium_base::transactions::PayloadLike;
1157        match value.payload.require()? {
1158            account_transaction_payload::Payload::RawPayload(rp) => {
1159                Self::try_from(rp).map_err(|_| {
1160                    tonic::Status::invalid_argument("Payload size exceeds maximum allowed.")
1161                })
1162            }
1163            account_transaction_payload::Payload::DeployModule(dm) => {
1164                let module = match dm.module.require()? {
1165                    versioned_module_source::Module::V0(source) => {
1166                        concordium_base::smart_contracts::WasmModule {
1167                            version: concordium_base::smart_contracts::WasmVersion::V0,
1168                            source: source.value.into(),
1169                        }
1170                    }
1171                    versioned_module_source::Module::V1(source) => {
1172                        concordium_base::smart_contracts::WasmModule {
1173                            version: concordium_base::smart_contracts::WasmVersion::V1,
1174                            source: source.value.into(),
1175                        }
1176                    }
1177                };
1178                Ok(concordium_base::transactions::Payload::DeployModule { module }.encode())
1179            }
1180            account_transaction_payload::Payload::InitContract(ic) => {
1181                let payload = concordium_base::transactions::InitContractPayload {
1182                    amount: ic.amount.require()?.into(),
1183                    mod_ref: ic.module_ref.require()?.try_into()?,
1184                    init_name: ic.init_name.require()?.try_into()?,
1185                    param: ic.parameter.require()?.try_into()?,
1186                };
1187                Ok(concordium_base::transactions::Payload::InitContract { payload }.encode())
1188            }
1189            account_transaction_payload::Payload::UpdateContract(uc) => {
1190                let payload = concordium_base::transactions::UpdateContractPayload {
1191                    amount: uc.amount.require()?.into(),
1192                    address: uc.address.require()?.into(),
1193                    receive_name: uc.receive_name.require()?.try_into()?,
1194                    message: uc.parameter.require()?.try_into()?,
1195                };
1196                Ok(concordium_base::transactions::Payload::Update { payload }.encode())
1197            }
1198            account_transaction_payload::Payload::Transfer(t) => {
1199                let payload = concordium_base::transactions::Payload::Transfer {
1200                    to_address: t.receiver.require()?.try_into()?,
1201                    amount: t.amount.require()?.into(),
1202                };
1203                Ok(payload.encode())
1204            }
1205            account_transaction_payload::Payload::TransferWithMemo(t) => {
1206                let payload = concordium_base::transactions::Payload::TransferWithMemo {
1207                    to_address: t.receiver.require()?.try_into()?,
1208                    amount: t.amount.require()?.into(),
1209                    memo: t.memo.require()?.try_into()?,
1210                };
1211                Ok(payload.encode())
1212            }
1213            account_transaction_payload::Payload::RegisterData(t) => {
1214                let payload = concordium_base::transactions::Payload::RegisterData {
1215                    data: t.try_into()?,
1216                };
1217                Ok(payload.encode())
1218            }
1219        }
1220    }
1221}
1222
1223impl TryFrom<Signature> for concordium_base::common::types::Signature {
1224    type Error = tonic::Status;
1225
1226    fn try_from(value: Signature) -> Result<Self, Self::Error> {
1227        if value.value.len() <= usize::from(u16::MAX) {
1228            Ok(Self { sig: value.value })
1229        } else {
1230            Err(tonic::Status::invalid_argument("Signature is too large."))
1231        }
1232    }
1233}
1234
1235impl TryFrom<AccountTransactionSignature> for concordium_base::common::types::TransactionSignature {
1236    type Error = tonic::Status;
1237
1238    fn try_from(value: AccountTransactionSignature) -> Result<Self, Self::Error> {
1239        let signatures = value
1240            .signatures
1241            .into_iter()
1242            .map(|(ci, m)| {
1243                let ci = u8::try_from(ci)
1244                    .map_err(|_| tonic::Status::invalid_argument("Invalid credential index."))?;
1245                let cred_sigs = m
1246                    .signatures
1247                    .into_iter()
1248                    .map(|(ki, sig)| {
1249                        let ki = u8::try_from(ki)
1250                            .map_err(|_| tonic::Status::invalid_argument("Invalid key index."))?;
1251                        let sig = sig.try_into()?;
1252                        Ok::<_, tonic::Status>((ki.into(), sig))
1253                    })
1254                    .collect::<Result<_, _>>()?;
1255                Ok::<_, tonic::Status>((ci.into(), cred_sigs))
1256            })
1257            .collect::<Result<_, _>>()?;
1258        Ok(Self { signatures })
1259    }
1260}
1261
1262impl TryFrom<AccountTransaction>
1263    for concordium_base::transactions::AccountTransaction<
1264        concordium_base::transactions::EncodedPayload,
1265    >
1266{
1267    type Error = tonic::Status;
1268
1269    fn try_from(value: AccountTransaction) -> Result<Self, Self::Error> {
1270        let payload: concordium_base::transactions::EncodedPayload =
1271            value.payload.require()?.try_into()?;
1272        let payload_size = payload.size();
1273        let header = {
1274            let header = value.header.require()?;
1275            let sender = header.sender.require()?.try_into()?;
1276            let nonce = header.sequence_number.require()?.into();
1277            let energy_amount = header.energy_amount.require()?.into();
1278            let expiry = header.expiry.require()?.into();
1279            concordium_base::transactions::TransactionHeader {
1280                sender,
1281                nonce,
1282                energy_amount,
1283                payload_size,
1284                expiry,
1285            }
1286        };
1287        Ok(Self {
1288            signature: value.signature.require()?.try_into()?,
1289            header,
1290            payload,
1291        })
1292    }
1293}
1294
1295impl TryFrom<CredentialDeployment>
1296    for crate::id::types::AccountCredentialMessage<
1297        crate::id::constants::IpPairing,
1298        crate::id::constants::ArCurve,
1299        crate::id::constants::AttributeKind,
1300    >
1301{
1302    type Error = tonic::Status;
1303
1304    fn try_from(value: CredentialDeployment) -> Result<Self, Self::Error> {
1305        let message_expiry = value.message_expiry.require()?.into();
1306        let credential_deployment::Payload::RawPayload(data) = value.payload.require()?;
1307        let credential = consume(&data)?;
1308        Ok(Self {
1309            message_expiry,
1310            credential,
1311        })
1312    }
1313}
1314
1315impl TryFrom<SignatureMap> for concordium_base::updates::UpdateInstructionSignature {
1316    type Error = tonic::Status;
1317
1318    fn try_from(value: SignatureMap) -> Result<Self, Self::Error> {
1319        let signatures = value
1320            .signatures
1321            .into_iter()
1322            .map(|(k, sig)| {
1323                let k = u16::try_from(k)
1324                    .map_err(|_| tonic::Status::invalid_argument("Update key index too large."))?;
1325                let sig = sig.try_into()?;
1326                Ok::<_, tonic::Status>((k.into(), sig))
1327            })
1328            .collect::<Result<_, _>>()?;
1329        Ok(Self { signatures })
1330    }
1331}
1332
1333impl TryFrom<UpdateInstruction> for concordium_base::updates::UpdateInstruction {
1334    type Error = tonic::Status;
1335
1336    fn try_from(value: UpdateInstruction) -> Result<Self, Self::Error> {
1337        let header = value.header.require()?;
1338        let update_instruction_payload::Payload::RawPayload(payload) =
1339            value.payload.require()?.payload.require()?;
1340        let header = concordium_base::updates::UpdateHeader {
1341            seq_number: header.sequence_number.require()?.into(),
1342            effective_time: header.effective_time.require()?.into(),
1343            timeout: header.timeout.require()?.into(),
1344            payload_size: (payload.len() as u32).into(), /* as is safe since
1345                                                          * this is coming from the node, from
1346                                                          * a block */
1347        };
1348        let signatures: concordium_base::updates::UpdateInstructionSignature =
1349            value.signatures.require()?.try_into()?;
1350        let payload = updates::EncodedUpdatePayload::from(payload);
1351        Ok(Self {
1352            header,
1353            payload,
1354            signatures,
1355        })
1356    }
1357}
1358
1359impl TryFrom<BlockItem>
1360    for Upward<
1361        concordium_base::transactions::BlockItem<concordium_base::transactions::EncodedPayload>,
1362    >
1363{
1364    type Error = tonic::Status;
1365
1366    fn try_from(value: BlockItem) -> Result<Self, Self::Error> {
1367        if let Some(item) = value.block_item {
1368            Ok(Upward::Known(item.try_into()?))
1369        } else {
1370            Ok(Upward::Unknown(()))
1371        }
1372    }
1373}
1374
1375impl TryFrom<block_item::BlockItem>
1376    for concordium_base::transactions::BlockItem<concordium_base::transactions::EncodedPayload>
1377{
1378    type Error = tonic::Status;
1379
1380    fn try_from(item: block_item::BlockItem) -> Result<Self, Self::Error> {
1381        type Item =
1382            concordium_base::transactions::BlockItem<concordium_base::transactions::EncodedPayload>;
1383        let out = match item {
1384            block_item::BlockItem::AccountTransaction(at) => {
1385                Item::AccountTransaction(at.try_into()?)
1386            }
1387            block_item::BlockItem::CredentialDeployment(cd) => {
1388                Item::CredentialDeployment(Box::new(cd.try_into()?))
1389            }
1390            block_item::BlockItem::UpdateInstruction(ui) => Item::UpdateInstruction(ui.try_into()?),
1391        };
1392        Ok(out)
1393    }
1394}
1395
1396impl TryFrom<AccountTransactionDetails> for super::types::AccountTransactionDetails {
1397    type Error = tonic::Status;
1398
1399    fn try_from(v: AccountTransactionDetails) -> Result<Self, Self::Error> {
1400        Ok(Self {
1401            cost: v.cost.require()?.into(),
1402            sender: v.sender.require()?.try_into()?,
1403            effects: Upward::from(v.effects.map(TryFrom::try_from).transpose()?),
1404        })
1405    }
1406}
1407
1408impl TryFrom<BlockItemSummary> for super::types::BlockItemSummary {
1409    type Error = tonic::Status;
1410
1411    fn try_from(value: BlockItemSummary) -> Result<Self, Self::Error> {
1412        Ok(Self {
1413            index: value.index.require()?.into(),
1414            energy_cost: value.energy_cost.require()?.into(),
1415            hash: value.hash.require()?.try_into()?,
1416            details: Upward::from(value.details.map(TryFrom::try_from).transpose()?),
1417        })
1418    }
1419}
1420
1421impl TryFrom<block_item_summary::Details> for super::types::BlockItemSummaryDetails {
1422    type Error = tonic::Status;
1423
1424    fn try_from(value: block_item_summary::Details) -> Result<Self, Self::Error> {
1425        let out = match value {
1426            block_item_summary::Details::AccountTransaction(v) => {
1427                super::types::BlockItemSummaryDetails::AccountTransaction(v.try_into()?)
1428            }
1429            block_item_summary::Details::AccountCreation(v) => {
1430                super::types::BlockItemSummaryDetails::AccountCreation(
1431                    super::types::AccountCreationDetails {
1432                        credential_type: v.credential_type().into(),
1433                        address: v.address.require()?.try_into()?,
1434                        reg_id: v.reg_id.require()?.try_into()?,
1435                    },
1436                )
1437            }
1438            block_item_summary::Details::Update(v) => {
1439                super::types::BlockItemSummaryDetails::Update(super::types::UpdateDetails {
1440                    effective_time: v.effective_time.require()?.into(),
1441                    payload: Upward::from(
1442                        v.payload
1443                            .map(super::types::UpdatePayload::try_from)
1444                            .transpose()?,
1445                    ),
1446                })
1447            }
1448            block_item_summary::Details::TokenCreation(v) => {
1449                super::types::BlockItemSummaryDetails::TokenCreationDetails(
1450                    super::types::TokenCreationDetails {
1451                        create_plt: v.create_plt.require()?.try_into()?,
1452                        events: v
1453                            .events
1454                            .into_iter()
1455                            .map(TryInto::try_into)
1456                            .collect::<Result<_, tonic::Status>>()?,
1457                    },
1458                )
1459            }
1460        };
1461        Ok(out)
1462    }
1463}
1464
1465impl TryFrom<ElectionDifficulty> for super::types::ElectionDifficulty {
1466    type Error = tonic::Status;
1467
1468    fn try_from(value: ElectionDifficulty) -> Result<Self, Self::Error> {
1469        Self::new(value.value.require()?.parts_per_hundred_thousand).ok_or_else(|| {
1470            tonic::Status::internal("Election difficulty more than 1, which is not allowed.")
1471        })
1472    }
1473}
1474
1475impl TryFrom<UpdatePayload> for super::types::UpdatePayload {
1476    type Error = tonic::Status;
1477
1478    fn try_from(value: UpdatePayload) -> Result<Self, Self::Error> {
1479        Ok(match value.payload.require()? {
1480            update_payload::Payload::ProtocolUpdate(v) => Self::Protocol(v.try_into()?),
1481            update_payload::Payload::ElectionDifficultyUpdate(v) => {
1482                Self::ElectionDifficulty(v.try_into()?)
1483            }
1484            update_payload::Payload::EuroPerEnergyUpdate(v) => Self::EuroPerEnergy(v.try_into()?),
1485            update_payload::Payload::MicroCcdPerEuroUpdate(v) => {
1486                Self::MicroGTUPerEuro(v.try_into()?)
1487            }
1488            update_payload::Payload::FoundationAccountUpdate(v) => {
1489                Self::FoundationAccount(v.try_into()?)
1490            }
1491            update_payload::Payload::MintDistributionUpdate(v) => {
1492                Self::MintDistribution(v.try_into()?)
1493            }
1494            update_payload::Payload::TransactionFeeDistributionUpdate(v) => {
1495                Self::TransactionFeeDistribution(v.try_into()?)
1496            }
1497            update_payload::Payload::GasRewardsUpdate(v) => Self::GASRewards(v.try_into()?),
1498            update_payload::Payload::BakerStakeThresholdUpdate(v) => {
1499                Self::BakerStakeThreshold(v.try_into()?)
1500            }
1501            update_payload::Payload::RootUpdate(v) => {
1502                Self::Root(match v.update_type.require()? {
1503                    root_update::UpdateType::RootKeysUpdate(u) => {
1504                        super::types::RootUpdate::RootKeysUpdate(u.try_into()?)
1505                    }
1506                    root_update::UpdateType::Level1KeysUpdate(u) => {
1507                        super::types::RootUpdate::Level1KeysUpdate(u.try_into()?)
1508                    }
1509                    root_update::UpdateType::Level2KeysUpdateV0(u) => {
1510                        super::types::RootUpdate::Level2KeysUpdate(Box::new(u.try_into()?))
1511                    }
1512                    root_update::UpdateType::Level2KeysUpdateV1(u) => {
1513                        super::types::RootUpdate::Level2KeysUpdateV1(Box::new(u.try_into()?))
1514                    }
1515                })
1516            }
1517            update_payload::Payload::Level1Update(v) => {
1518                Self::Level1(match v.update_type.require()? {
1519                    level1_update::UpdateType::Level1KeysUpdate(u) => {
1520                        super::types::Level1Update::Level1KeysUpdate(u.try_into()?)
1521                    }
1522                    level1_update::UpdateType::Level2KeysUpdateV0(u) => {
1523                        super::types::Level1Update::Level2KeysUpdate(Box::new(u.try_into()?))
1524                    }
1525                    level1_update::UpdateType::Level2KeysUpdateV1(u) => {
1526                        super::types::Level1Update::Level2KeysUpdateV1(Box::new(u.try_into()?))
1527                    }
1528                })
1529            }
1530            update_payload::Payload::AddAnonymityRevokerUpdate(v) => {
1531                Self::AddAnonymityRevoker(Box::new(v.try_into()?))
1532            }
1533            update_payload::Payload::AddIdentityProviderUpdate(v) => {
1534                Self::AddIdentityProvider(Box::new(v.try_into()?))
1535            }
1536            update_payload::Payload::CooldownParametersCpv1Update(v) => {
1537                Self::CooldownParametersCPV1(v.try_into()?)
1538            }
1539            update_payload::Payload::PoolParametersCpv1Update(v) => {
1540                Self::PoolParametersCPV1(v.try_into()?)
1541            }
1542            update_payload::Payload::TimeParametersCpv1Update(v) => {
1543                Self::TimeParametersCPV1(v.try_into()?)
1544            }
1545            update_payload::Payload::MintDistributionCpv1Update(v) => {
1546                Self::MintDistributionCPV1(v.try_into()?)
1547            }
1548            update_payload::Payload::GasRewardsCpv2Update(v) => Self::GASRewardsCPV2(v.try_into()?),
1549            update_payload::Payload::TimeoutParametersUpdate(v) => {
1550                Self::TimeoutParametersCPV2(v.try_into()?)
1551            }
1552            update_payload::Payload::MinBlockTimeUpdate(v) => Self::MinBlockTimeCPV2(v.into()),
1553            update_payload::Payload::BlockEnergyLimitUpdate(v) => {
1554                Self::BlockEnergyLimitCPV2(v.into())
1555            }
1556            update_payload::Payload::FinalizationCommitteeParametersUpdate(v) => {
1557                Self::FinalizationCommitteeParametersCPV2(v.try_into()?)
1558            }
1559            update_payload::Payload::ValidatorScoreParametersUpdate(v) => {
1560                Self::ValidatorScoreParametersCPV3(v.try_into()?)
1561            }
1562            update_payload::Payload::CreatePltUpdate(create_plt) => {
1563                Self::CreatePlt(create_plt.try_into()?)
1564            }
1565        })
1566    }
1567}
1568
1569impl TryFrom<super::generated::plt::CreatePlt> for concordium_base::updates::CreatePlt {
1570    type Error = tonic::Status;
1571
1572    fn try_from(value: super::generated::plt::CreatePlt) -> Result<Self, Self::Error> {
1573        Ok(Self {
1574            token_id: value.token_id.require()?.try_into()?,
1575            token_module: value.token_module.require()?.try_into()?,
1576            decimals: value.decimals.try_into().map_err(|_| {
1577                tonic::Status::internal("Unexpected integer size for token decimals.")
1578            })?,
1579            initialization_parameters: value.initialization_parameters.require()?.into(),
1580        })
1581    }
1582}
1583
1584impl TryFrom<CapitalBound> for super::types::CapitalBound {
1585    type Error = tonic::Status;
1586
1587    fn try_from(value: CapitalBound) -> Result<Self, Self::Error> {
1588        Ok(Self {
1589            bound: value.value.require()?.into(),
1590        })
1591    }
1592}
1593
1594impl TryFrom<InclusiveRangeAmountFraction>
1595    for super::types::InclusiveRange<super::types::AmountFraction>
1596{
1597    type Error = tonic::Status;
1598
1599    fn try_from(value: InclusiveRangeAmountFraction) -> Result<Self, Self::Error> {
1600        let min = value.min.require()?.into();
1601        let max = value.max.require()?.into();
1602        if min <= max {
1603            Ok(Self { min, max })
1604        } else {
1605            Err(tonic::Status::internal(
1606                "Lower bound must not be more than the upper bound.",
1607            ))
1608        }
1609    }
1610}
1611
1612impl From<DurationSeconds> for super::types::DurationSeconds {
1613    fn from(value: DurationSeconds) -> Self {
1614        Self {
1615            seconds: value.value,
1616        }
1617    }
1618}
1619
1620impl TryFrom<IpInfo> for crate::id::types::IpInfo<IpPairing> {
1621    type Error = tonic::Status;
1622
1623    fn try_from(value: IpInfo) -> Result<Self, Self::Error> {
1624        Ok(Self {
1625            ip_identity: crate::id::types::IpIdentity(value.identity.require()?.value),
1626            ip_description: value.description.require()?.into(),
1627            ip_verify_key: value.verify_key.require()?.try_into()?,
1628            ip_cdi_verify_key: value.cdi_verify_key.require()?.try_into()?,
1629        })
1630    }
1631}
1632
1633impl TryFrom<ArInfo> for crate::id::types::ArInfo<ArCurve> {
1634    type Error = tonic::Status;
1635
1636    fn try_from(value: ArInfo) -> Result<Self, Self::Error> {
1637        Ok(Self {
1638            ar_identity: crate::id::types::ArIdentity::try_from(value.identity.require()?.value)
1639                .map_err(tonic::Status::internal)?,
1640            ar_description: value.description.require()?.into(),
1641            ar_public_key: value.public_key.require()?.try_into()?,
1642        })
1643    }
1644}
1645
1646impl From<Description> for crate::id::types::Description {
1647    fn from(value: Description) -> Self {
1648        Self {
1649            name: value.name,
1650            url: value.url,
1651            description: value.description,
1652        }
1653    }
1654}
1655
1656impl TryFrom<AuthorizationsV0> for super::types::AuthorizationsV0 {
1657    type Error = tonic::Status;
1658
1659    fn try_from(value: AuthorizationsV0) -> Result<Self, Self::Error> {
1660        Ok(Self {
1661            keys: value
1662                .keys
1663                .into_iter()
1664                .map(TryInto::try_into)
1665                .collect::<Result<_, tonic::Status>>()?,
1666            emergency: value.emergency.require()?.try_into()?,
1667            protocol: value.protocol.require()?.try_into()?,
1668            election_difficulty: value.parameter_consensus.require()?.try_into()?,
1669            euro_per_energy: value.parameter_euro_per_energy.require()?.try_into()?,
1670            micro_gtu_per_euro: value.parameter_micro_ccd_per_euro.require()?.try_into()?,
1671            foundation_account: value.parameter_foundation_account.require()?.try_into()?,
1672            mint_distribution: value.parameter_mint_distribution.require()?.try_into()?,
1673            transaction_fee_distribution: value
1674                .parameter_transaction_fee_distribution
1675                .require()?
1676                .try_into()?,
1677            param_gas_rewards: value.parameter_gas_rewards.require()?.try_into()?,
1678            pool_parameters: value.pool_parameters.require()?.try_into()?,
1679            add_anonymity_revoker: value.add_anonymity_revoker.require()?.try_into()?,
1680            add_identity_provider: value.add_identity_provider.require()?.try_into()?,
1681        })
1682    }
1683}
1684
1685impl TryFrom<AuthorizationsV1> for super::types::AuthorizationsV1 {
1686    type Error = tonic::Status;
1687
1688    fn try_from(value: AuthorizationsV1) -> Result<Self, Self::Error> {
1689        Ok(Self {
1690            v0: value.v0.require()?.try_into()?,
1691            cooldown_parameters: value.parameter_cooldown.require()?.try_into()?,
1692            time_parameters: value.parameter_time.require()?.try_into()?,
1693            create_plt: value.create_plt.map(|x| x.try_into()).transpose()?,
1694        })
1695    }
1696}
1697
1698impl TryFrom<AuthorizationsV0> for chain_parameters::Level2Keys {
1699    type Error = tonic::Status;
1700
1701    fn try_from(value: AuthorizationsV0) -> Result<Self, Self::Error> {
1702        Ok(Self {
1703            keys: value
1704                .keys
1705                .into_iter()
1706                .map(TryInto::try_into)
1707                .collect::<Result<_, tonic::Status>>()?,
1708            emergency: value.emergency.map(TryInto::try_into).transpose()?,
1709            protocol: value.protocol.map(TryInto::try_into).transpose()?,
1710            consensus: value
1711                .parameter_consensus
1712                .map(TryInto::try_into)
1713                .transpose()?,
1714            euro_per_energy: value
1715                .parameter_euro_per_energy
1716                .map(TryInto::try_into)
1717                .transpose()?,
1718            micro_ccd_per_euro: value
1719                .parameter_micro_ccd_per_euro
1720                .map(TryInto::try_into)
1721                .transpose()?,
1722            foundation_account: value
1723                .parameter_foundation_account
1724                .map(TryInto::try_into)
1725                .transpose()?,
1726            mint_distribution: value
1727                .parameter_mint_distribution
1728                .map(TryInto::try_into)
1729                .transpose()?,
1730            transaction_fee_distribution: value
1731                .parameter_transaction_fee_distribution
1732                .map(TryInto::try_into)
1733                .transpose()?,
1734            param_gas_rewards: value
1735                .parameter_gas_rewards
1736                .map(TryInto::try_into)
1737                .transpose()?,
1738            pool_parameters: value.pool_parameters.map(TryInto::try_into).transpose()?,
1739            add_anonymity_revoker: value
1740                .add_anonymity_revoker
1741                .map(TryInto::try_into)
1742                .transpose()?,
1743            add_identity_provider: value
1744                .add_identity_provider
1745                .map(TryInto::try_into)
1746                .transpose()?,
1747            cooldown_parameters: None,
1748            time_parameters: None,
1749            create_plt: None,
1750        })
1751    }
1752}
1753
1754impl TryFrom<AuthorizationsV1> for chain_parameters::Level2Keys {
1755    type Error = tonic::Status;
1756
1757    fn try_from(value: AuthorizationsV1) -> Result<Self, Self::Error> {
1758        let keys: Self = value.v0.require()?.try_into()?;
1759        Ok(Self {
1760            cooldown_parameters: value
1761                .parameter_cooldown
1762                .map(TryInto::try_into)
1763                .transpose()?,
1764            time_parameters: value.parameter_time.map(TryInto::try_into).transpose()?,
1765            create_plt: value.create_plt.map(|x| x.try_into()).transpose()?,
1766            ..keys
1767        })
1768    }
1769}
1770
1771impl TryFrom<AccessStructure> for super::types::AccessStructure {
1772    type Error = tonic::Status;
1773
1774    fn try_from(value: AccessStructure) -> Result<Self, Self::Error> {
1775        let authorized_keys = value
1776            .access_public_keys
1777            .into_iter()
1778            .map(TryInto::try_into)
1779            .collect::<Result<_, tonic::Status>>()?;
1780        let threshold = value.access_threshold.require()?.try_into()?;
1781        Ok(Self {
1782            authorized_keys,
1783            threshold,
1784        })
1785    }
1786}
1787
1788impl TryFrom<UpdateKeysIndex> for super::types::UpdateKeysIndex {
1789    type Error = tonic::Status;
1790
1791    fn try_from(value: UpdateKeysIndex) -> Result<Self, Self::Error> {
1792        Ok(Self {
1793            index: value.value.try_into().map_err(|_| {
1794                tonic::Status::internal("Invalid update keys index: could not fit into a u16.")
1795            })?,
1796        })
1797    }
1798}
1799
1800impl TryFrom<UpdateKeysThreshold> for super::types::UpdateKeysThreshold {
1801    type Error = tonic::Status;
1802
1803    fn try_from(value: UpdateKeysThreshold) -> Result<Self, Self::Error> {
1804        Self::try_from(
1805            u16::try_from(value.value)
1806                .map_err(|_| tonic::Status::internal("Threshold could not fit into a u16."))?,
1807        )
1808        .map_err(|_| tonic::Status::invalid_argument("UpdateKeysThreshold cannot be 0."))
1809    }
1810}
1811
1812impl TryFrom<MintRate> for super::types::MintRate {
1813    type Error = tonic::Status;
1814
1815    fn try_from(value: MintRate) -> Result<Self, Self::Error> {
1816        Ok(Self {
1817            mantissa: value.mantissa,
1818            exponent: value.exponent.try_into().map_err(|_| {
1819                tonic::Status::internal(
1820                    "Invalid exponent value. Could not be represented in an u8.",
1821                )
1822            })?,
1823        })
1824    }
1825}
1826
1827impl From<TransactionTime> for super::super::common::types::TransactionTime {
1828    fn from(value: TransactionTime) -> Self {
1829        Self {
1830            seconds: value.value,
1831        }
1832    }
1833}
1834
1835impl From<CredentialType> for super::types::CredentialType {
1836    fn from(value: CredentialType) -> Self {
1837        match value {
1838            CredentialType::Initial => Self::Initial,
1839            CredentialType::Normal => Self::Normal,
1840        }
1841    }
1842}
1843
1844impl TryFrom<AccountTransactionEffects> for super::types::AccountTransactionEffects {
1845    type Error = tonic::Status;
1846
1847    fn try_from(value: AccountTransactionEffects) -> Result<Self, Self::Error> {
1848        match value.effect.require()? {
1849            account_transaction_effects::Effect::None(n) => Ok(Self::None {
1850                transaction_type: {
1851                    match n.transaction_type {
1852                        None => None,
1853                        Some(tt) => Some(
1854                            super::types::TransactionType::try_from(tt)
1855                                .map_err(|e| tonic::Status::invalid_argument(e.to_string()))?,
1856                        ),
1857                    }
1858                },
1859                reject_reason: n
1860                    .reject_reason
1861                    .map(super::types::RejectReason::try_from)
1862                    .transpose()?
1863                    .into(),
1864            }),
1865            account_transaction_effects::Effect::AccountTransfer(at) => {
1866                let amount = at.amount.require()?.into();
1867                let to = at.receiver.require()?.try_into()?;
1868                match at.memo {
1869                    None => Ok(Self::AccountTransfer { amount, to }),
1870                    Some(memo) => Ok(Self::AccountTransferWithMemo {
1871                        amount,
1872                        to,
1873                        memo: memo.try_into()?,
1874                    }),
1875                }
1876            }
1877            account_transaction_effects::Effect::ModuleDeployed(module_ref) => {
1878                Ok(Self::ModuleDeployed {
1879                    module_ref: module_ref.try_into()?,
1880                })
1881            }
1882            account_transaction_effects::Effect::ContractInitialized(cie) => {
1883                Ok(Self::ContractInitialized {
1884                    data: super::types::ContractInitializedEvent {
1885                        contract_version: u8::try_from(cie.contract_version)
1886                            .map(WasmVersionInt)
1887                            .map_err(|err| {
1888                                tonic::Status::internal(format!(
1889                                    "Could not map contract version from i32 to u8: {err}"
1890                                ))
1891                            })?,
1892                        origin_ref: cie.origin_ref.require()?.try_into()?,
1893                        address: cie.address.require()?.into(),
1894                        amount: cie.amount.require()?.into(),
1895                        init_name: cie.init_name.require()?.try_into()?,
1896                        events: cie.events.into_iter().map(Into::into).collect(),
1897                        parameter: cie.parameter.map(TryInto::try_into).transpose()?,
1898                    },
1899                })
1900            }
1901            account_transaction_effects::Effect::ContractUpdateIssued(cui) => {
1902                let effects = cui
1903                    .effects
1904                    .into_iter()
1905                    .map(|trace| {
1906                        Ok(Upward::from(
1907                            trace
1908                                .element
1909                                .map(super::types::ContractTraceElement::try_from)
1910                                .transpose()?,
1911                        ))
1912                    })
1913                    .collect::<Result<_, tonic::Status>>()?;
1914                Ok(Self::ContractUpdateIssued { effects })
1915            }
1916            account_transaction_effects::Effect::BakerAdded(ba) => {
1917                let baker_added_event = super::types::BakerAddedEvent {
1918                    keys_event: ba.keys_event.require()?.try_into()?,
1919                    stake: ba.stake.require()?.into(),
1920                    restake_earnings: ba.restake_earnings,
1921                };
1922                Ok(Self::BakerAdded {
1923                    data: Box::new(baker_added_event),
1924                })
1925            }
1926            account_transaction_effects::Effect::BakerRemoved(baker_id) => Ok(Self::BakerRemoved {
1927                baker_id: baker_id.into(),
1928            }),
1929            account_transaction_effects::Effect::BakerStakeUpdated(bsu) => {
1930                let data = match bsu.update {
1931                    None => None,
1932                    Some(d) => Some(super::types::BakerStakeUpdatedData {
1933                        baker_id: d.baker_id.require()?.into(),
1934                        new_stake: d.new_stake.require()?.into(),
1935                        increased: d.increased,
1936                    }),
1937                };
1938                Ok(Self::BakerStakeUpdated { data })
1939            }
1940            account_transaction_effects::Effect::BakerRestakeEarningsUpdated(breu) => {
1941                Ok(Self::BakerRestakeEarningsUpdated {
1942                    baker_id: breu.baker_id.require()?.into(),
1943                    restake_earnings: breu.restake_earnings,
1944                })
1945            }
1946            account_transaction_effects::Effect::BakerKeysUpdated(keys_event) => {
1947                Ok(Self::BakerKeysUpdated {
1948                    data: Box::new(keys_event.try_into()?),
1949                })
1950            }
1951            account_transaction_effects::Effect::EncryptedAmountTransferred(eat) => {
1952                let removed = Box::new(eat.removed.require()?.try_into()?);
1953                let added = Box::new(eat.added.require()?.try_into()?);
1954                match eat.memo {
1955                    None => Ok(Self::EncryptedAmountTransferred { removed, added }),
1956                    Some(memo) => Ok(Self::EncryptedAmountTransferredWithMemo {
1957                        removed,
1958                        added,
1959                        memo: memo.try_into()?,
1960                    }),
1961                }
1962            }
1963            account_transaction_effects::Effect::TransferredToEncrypted(esaae) => {
1964                Ok(Self::TransferredToEncrypted {
1965                    data: Box::new(super::types::EncryptedSelfAmountAddedEvent {
1966                        account: esaae.account.require()?.try_into()?,
1967                        new_amount: esaae.new_amount.require()?.try_into()?,
1968                        amount: esaae.amount.require()?.into(),
1969                    }),
1970                })
1971            }
1972            account_transaction_effects::Effect::TransferredToPublic(ttp) => {
1973                Ok(Self::TransferredToPublic {
1974                    removed: Box::new(ttp.removed.require()?.try_into()?),
1975                    amount: ttp.amount.require()?.into(),
1976                })
1977            }
1978            account_transaction_effects::Effect::TransferredWithSchedule(tws) => {
1979                let to = tws.receiver.require()?.try_into()?;
1980                let amount = tws
1981                    .amount
1982                    .into_iter()
1983                    .map(TryInto::try_into)
1984                    .collect::<Result<_, tonic::Status>>()?;
1985                match tws.memo {
1986                    None => Ok(Self::TransferredWithSchedule { to, amount }),
1987                    Some(memo) => Ok(Self::TransferredWithScheduleAndMemo {
1988                        to,
1989                        amount,
1990                        memo: memo.try_into()?,
1991                    }),
1992                }
1993            }
1994            account_transaction_effects::Effect::CredentialKeysUpdated(cri) => {
1995                Ok(Self::CredentialKeysUpdated {
1996                    cred_id: cri.try_into()?,
1997                })
1998            }
1999            account_transaction_effects::Effect::CredentialsUpdated(cu) => {
2000                Ok(Self::CredentialsUpdated {
2001                    new_cred_ids: cu
2002                        .new_cred_ids
2003                        .into_iter()
2004                        .map(TryInto::try_into)
2005                        .collect::<Result<_, tonic::Status>>()?,
2006                    removed_cred_ids: cu
2007                        .removed_cred_ids
2008                        .into_iter()
2009                        .map(TryInto::try_into)
2010                        .collect::<Result<_, tonic::Status>>()?,
2011                    new_threshold: cu.new_threshold.require()?.try_into()?,
2012                })
2013            }
2014            account_transaction_effects::Effect::DataRegistered(rd) => Ok(Self::DataRegistered {
2015                data: rd.try_into()?,
2016            }),
2017            account_transaction_effects::Effect::BakerConfigured(bc) => Ok(Self::BakerConfigured {
2018                data: bc
2019                    .events
2020                    .into_iter()
2021                    .map(|event| {
2022                        Ok(Upward::from(
2023                            event
2024                                .event
2025                                .map(super::types::BakerEvent::try_from)
2026                                .transpose()?,
2027                        ))
2028                    })
2029                    .collect::<Result<_, tonic::Status>>()?,
2030            }),
2031            account_transaction_effects::Effect::DelegationConfigured(dc) => {
2032                Ok(Self::DelegationConfigured {
2033                    data: dc
2034                        .events
2035                        .into_iter()
2036                        .map(|event| {
2037                            Ok(Upward::from(
2038                                event
2039                                    .event
2040                                    .map(super::types::DelegationEvent::try_from)
2041                                    .transpose()?,
2042                            ))
2043                        })
2044                        .collect::<Result<_, tonic::Status>>()?,
2045                })
2046            }
2047            account_transaction_effects::Effect::TokenUpdateEffect(token_effect) => {
2048                Ok(Self::TokenUpdate {
2049                    events: token_effect
2050                        .events
2051                        .into_iter()
2052                        .map(TryInto::try_into)
2053                        .collect::<Result<_, tonic::Status>>()?,
2054                })
2055            }
2056        }
2057    }
2058}
2059
2060impl TryFrom<contract_trace_element::Element> for super::types::ContractTraceElement {
2061    type Error = tonic::Status;
2062
2063    fn try_from(element: contract_trace_element::Element) -> Result<Self, Self::Error> {
2064        Ok(match element {
2065            contract_trace_element::Element::Updated(u) => {
2066                super::types::ContractTraceElement::Updated {
2067                    data: u.try_into()?,
2068                }
2069            }
2070            contract_trace_element::Element::Transferred(t) => {
2071                super::types::ContractTraceElement::Transferred {
2072                    from: t.sender.require()?.into(),
2073                    amount: t.amount.require()?.into(),
2074                    to: t.receiver.require()?.try_into()?,
2075                }
2076            }
2077            contract_trace_element::Element::Interrupted(i) => {
2078                super::types::ContractTraceElement::Interrupted {
2079                    address: i.address.require()?.into(),
2080                    events: i.events.into_iter().map(Into::into).collect(),
2081                }
2082            }
2083            contract_trace_element::Element::Resumed(r) => {
2084                super::types::ContractTraceElement::Resumed {
2085                    address: r.address.require()?.into(),
2086                    success: r.success,
2087                }
2088            }
2089            contract_trace_element::Element::Upgraded(r) => {
2090                super::types::ContractTraceElement::Upgraded {
2091                    address: r.address.require()?.into(),
2092                    from: r.from.require()?.try_into()?,
2093                    to: r.to.require()?.try_into()?,
2094                }
2095            }
2096        })
2097    }
2098}
2099
2100impl TryFrom<delegation_event::Event> for super::types::DelegationEvent {
2101    type Error = tonic::Status;
2102
2103    fn try_from(value: delegation_event::Event) -> Result<Self, Self::Error> {
2104        Ok(match value {
2105            delegation_event::Event::DelegationStakeIncreased(v) => {
2106                Self::DelegationStakeIncreased {
2107                    delegator_id: v.delegator_id.require()?.try_into()?,
2108                    new_stake: v.new_stake.require()?.into(),
2109                }
2110            }
2111            delegation_event::Event::DelegationStakeDecreased(v) => {
2112                Self::DelegationStakeDecreased {
2113                    delegator_id: v.delegator_id.require()?.try_into()?,
2114                    new_stake: v.new_stake.require()?.into(),
2115                }
2116            }
2117            delegation_event::Event::DelegationSetRestakeEarnings(v) => {
2118                Self::DelegationSetRestakeEarnings {
2119                    delegator_id: v.delegator_id.require()?.try_into()?,
2120                    restake_earnings: v.restake_earnings,
2121                }
2122            }
2123            delegation_event::Event::DelegationSetDelegationTarget(v) => {
2124                Self::DelegationSetDelegationTarget {
2125                    delegator_id: v.delegator_id.require()?.try_into()?,
2126                    delegation_target: v.delegation_target.require()?.try_into()?,
2127                }
2128            }
2129            delegation_event::Event::DelegationAdded(v) => Self::DelegationAdded {
2130                delegator_id: v.try_into()?,
2131            },
2132            delegation_event::Event::DelegationRemoved(v) => Self::DelegationRemoved {
2133                delegator_id: v.try_into()?,
2134            },
2135            delegation_event::Event::BakerRemoved(v) => Self::BakerRemoved {
2136                baker_id: v.baker_id.require()?.into(),
2137            },
2138        })
2139    }
2140}
2141
2142impl TryFrom<DelegatorId> for super::types::DelegatorId {
2143    type Error = tonic::Status;
2144
2145    fn try_from(value: DelegatorId) -> Result<Self, Self::Error> {
2146        Ok(Self {
2147            id: value.id.require()?.into(),
2148        })
2149    }
2150}
2151
2152impl TryFrom<baker_event::Event> for super::types::BakerEvent {
2153    type Error = tonic::Status;
2154
2155    fn try_from(value: baker_event::Event) -> Result<Self, Self::Error> {
2156        Ok(match value {
2157            baker_event::Event::BakerAdded(v) => Self::BakerAdded {
2158                data: Box::new(super::types::BakerAddedEvent {
2159                    keys_event: v.keys_event.require()?.try_into()?,
2160                    stake: v.stake.require()?.into(),
2161                    restake_earnings: v.restake_earnings,
2162                }),
2163            },
2164            baker_event::Event::BakerRemoved(v) => Self::BakerRemoved { baker_id: v.into() },
2165            baker_event::Event::BakerStakeIncreased(v) => Self::BakerStakeIncreased {
2166                baker_id: v.baker_id.require()?.into(),
2167                new_stake: v.new_stake.require()?.into(),
2168            },
2169            baker_event::Event::BakerStakeDecreased(v) => Self::BakerStakeDecreased {
2170                baker_id: v.baker_id.require()?.into(),
2171                new_stake: v.new_stake.require()?.into(),
2172            },
2173            baker_event::Event::BakerRestakeEarningsUpdated(v) => {
2174                Self::BakerRestakeEarningsUpdated {
2175                    baker_id: v.baker_id.require()?.into(),
2176                    restake_earnings: v.restake_earnings,
2177                }
2178            }
2179            baker_event::Event::BakerKeysUpdated(v) => Self::BakerKeysUpdated {
2180                data: Box::new(v.try_into()?),
2181            },
2182            baker_event::Event::BakerSetOpenStatus(v) => {
2183                let open_status = Upward::from(OpenStatus::try_from(v.open_status).ok())
2184                    .map(super::types::OpenStatus::from);
2185                Self::BakerSetOpenStatus {
2186                    baker_id: v.baker_id.require()?.into(),
2187                    open_status,
2188                }
2189            }
2190            baker_event::Event::BakerSetMetadataUrl(v) => Self::BakerSetMetadataURL {
2191                baker_id: v.baker_id.require()?.into(),
2192                metadata_url: v.url.try_into().map_err(|e| {
2193                    tonic::Status::invalid_argument(format!("Invalid argument: {}", e))
2194                })?,
2195            },
2196            baker_event::Event::BakerSetTransactionFeeCommission(v) => {
2197                Self::BakerSetTransactionFeeCommission {
2198                    baker_id: v.baker_id.require()?.into(),
2199                    transaction_fee_commission: v.transaction_fee_commission.require()?.into(),
2200                }
2201            }
2202            baker_event::Event::BakerSetBakingRewardCommission(v) => {
2203                Self::BakerSetBakingRewardCommission {
2204                    baker_id: v.baker_id.require()?.into(),
2205                    baking_reward_commission: v.baking_reward_commission.require()?.into(),
2206                }
2207            }
2208            baker_event::Event::BakerSetFinalizationRewardCommission(v) => {
2209                Self::BakerSetFinalizationRewardCommission {
2210                    baker_id: v.baker_id.require()?.into(),
2211                    finalization_reward_commission: v
2212                        .finalization_reward_commission
2213                        .require()?
2214                        .into(),
2215                }
2216            }
2217            baker_event::Event::DelegationRemoved(v) => Self::DelegationRemoved {
2218                delegator_id: v.delegator_id.require()?.try_into()?,
2219            },
2220            baker_event::Event::BakerSuspended(v) => Self::BakerSuspended {
2221                baker_id: v.baker_id.require()?.into(),
2222            },
2223            baker_event::Event::BakerResumed(v) => Self::BakerResumed {
2224                baker_id: v.baker_id.require()?.into(),
2225            },
2226        })
2227    }
2228}
2229
2230impl TryFrom<RegisteredData> for super::types::RegisteredData {
2231    type Error = tonic::Status;
2232
2233    fn try_from(value: RegisteredData) -> Result<Self, Self::Error> {
2234        value
2235            .value
2236            .try_into()
2237            .map_err(|e| tonic::Status::invalid_argument(format!("{}", e)))
2238    }
2239}
2240
2241impl TryFrom<NewRelease>
2242    for (
2243        super::super::common::types::Timestamp,
2244        super::super::common::types::Amount,
2245    )
2246{
2247    type Error = tonic::Status;
2248
2249    fn try_from(value: NewRelease) -> Result<Self, Self::Error> {
2250        let timestamp = super::super::common::types::Timestamp {
2251            millis: value.timestamp.require()?.value,
2252        };
2253        Ok((timestamp, value.amount.require()?.into()))
2254    }
2255}
2256
2257impl TryFrom<EncryptedAmountRemovedEvent> for super::types::EncryptedAmountRemovedEvent {
2258    type Error = tonic::Status;
2259
2260    fn try_from(value: EncryptedAmountRemovedEvent) -> Result<Self, Self::Error> {
2261        Ok(Self {
2262            account: value.account.require()?.try_into()?,
2263            new_amount: value.new_amount.require()?.try_into()?,
2264            input_amount: value.input_amount.require()?.try_into()?,
2265            up_to_index: crate::encrypted_transfers::types::EncryptedAmountAggIndex {
2266                index: value.up_to_index,
2267            },
2268        })
2269    }
2270}
2271
2272impl TryFrom<NewEncryptedAmountEvent> for super::types::NewEncryptedAmountEvent {
2273    type Error = tonic::Status;
2274
2275    fn try_from(value: NewEncryptedAmountEvent) -> Result<Self, Self::Error> {
2276        Ok(Self {
2277            receiver: value.receiver.require()?.try_into()?,
2278            new_index: crate::encrypted_transfers::types::EncryptedAmountIndex {
2279                index: value.new_index,
2280            },
2281            encrypted_amount: value.encrypted_amount.require()?.try_into()?,
2282        })
2283    }
2284}
2285
2286impl TryFrom<Memo> for super::types::Memo {
2287    type Error = tonic::Status;
2288
2289    fn try_from(value: Memo) -> Result<Self, Self::Error> {
2290        value
2291            .value
2292            .try_into()
2293            .map_err(|_| tonic::Status::invalid_argument("Memo is invalid because it is too big."))
2294    }
2295}
2296impl TryFrom<BakerKeysEvent> for super::types::BakerKeysEvent {
2297    type Error = tonic::Status;
2298
2299    fn try_from(value: BakerKeysEvent) -> Result<Self, Self::Error> {
2300        Ok(Self {
2301            baker_id: value.baker_id.require()?.into(),
2302            account: value.account.require()?.try_into()?,
2303            sign_key: value.sign_key.require()?.try_into()?,
2304            election_key: value.election_key.require()?.try_into()?,
2305            aggregation_key: value.aggregation_key.require()?.try_into()?,
2306        })
2307    }
2308}
2309
2310impl TryFrom<InstanceUpdatedEvent> for super::types::InstanceUpdatedEvent {
2311    type Error = tonic::Status;
2312
2313    fn try_from(value: InstanceUpdatedEvent) -> Result<Self, Self::Error> {
2314        Ok(Self {
2315            contract_version: u8::try_from(value.contract_version)
2316                .map(WasmVersionInt)
2317                .map_err(|err| {
2318                    tonic::Status::internal(format!(
2319                        "Could not map contract version from i32 to u8: {err}"
2320                    ))
2321                })?,
2322            address: value.address.require()?.into(),
2323            instigator: value.instigator.require()?.try_into()?,
2324            amount: value.amount.require()?.into(),
2325            message: value.parameter.require()?.try_into()?,
2326            receive_name: value.receive_name.require()?.try_into()?,
2327            events: value.events.into_iter().map(Into::into).collect(),
2328        })
2329    }
2330}
2331
2332impl From<ContractEvent> for super::types::smart_contracts::ContractEvent {
2333    fn from(value: ContractEvent) -> Self {
2334        value.value.into()
2335    }
2336}
2337
2338impl TryFrom<RejectReason> for super::types::RejectReason {
2339    type Error = tonic::Status;
2340
2341    fn try_from(value: RejectReason) -> Result<Self, Self::Error> {
2342        Ok(match value.reason.require()? {
2343            reject_reason::Reason::ModuleNotWf(_) => Self::ModuleNotWF,
2344            reject_reason::Reason::ModuleHashAlreadyExists(v) => Self::ModuleHashAlreadyExists {
2345                contents: v.try_into()?,
2346            },
2347            reject_reason::Reason::InvalidAccountReference(v) => Self::InvalidAccountReference {
2348                contents: v.try_into()?,
2349            },
2350            reject_reason::Reason::InvalidInitMethod(v) => Self::InvalidInitMethod {
2351                contents: (
2352                    v.module_ref.require()?.try_into()?,
2353                    v.init_name.require()?.try_into()?,
2354                ),
2355            },
2356            reject_reason::Reason::InvalidReceiveMethod(v) => Self::InvalidReceiveMethod {
2357                contents: (
2358                    v.module_ref.require()?.try_into()?,
2359                    v.receive_name.require()?.try_into()?,
2360                ),
2361            },
2362            reject_reason::Reason::InvalidModuleReference(v) => Self::InvalidModuleReference {
2363                contents: v.try_into()?,
2364            },
2365            reject_reason::Reason::InvalidContractAddress(v) => {
2366                Self::InvalidContractAddress { contents: v.into() }
2367            }
2368            reject_reason::Reason::RuntimeFailure(_) => Self::RuntimeFailure,
2369            reject_reason::Reason::AmountTooLarge(v) => Self::AmountTooLarge {
2370                contents: (v.address.require()?.try_into()?, v.amount.require()?.into()),
2371            },
2372            reject_reason::Reason::SerializationFailure(_) => Self::SerializationFailure,
2373            reject_reason::Reason::OutOfEnergy(_) => Self::OutOfEnergy,
2374            reject_reason::Reason::RejectedInit(v) => Self::RejectedInit {
2375                reject_reason: v.reject_reason,
2376            },
2377            reject_reason::Reason::RejectedReceive(v) => Self::RejectedReceive {
2378                reject_reason: v.reject_reason,
2379                contract_address: v.contract_address.require()?.into(),
2380                receive_name: v.receive_name.require()?.try_into()?,
2381                parameter: v.parameter.require()?.try_into()?,
2382            },
2383            reject_reason::Reason::InvalidProof(_) => Self::InvalidProof,
2384            reject_reason::Reason::AlreadyABaker(v) => Self::AlreadyABaker { contents: v.into() },
2385            reject_reason::Reason::NotABaker(v) => Self::NotABaker {
2386                contents: v.try_into()?,
2387            },
2388            reject_reason::Reason::InsufficientBalanceForBakerStake(_) => {
2389                Self::InsufficientBalanceForBakerStake
2390            }
2391            reject_reason::Reason::StakeUnderMinimumThresholdForBaking(_) => {
2392                Self::StakeUnderMinimumThresholdForBaking
2393            }
2394            reject_reason::Reason::BakerInCooldown(_) => Self::BakerInCooldown,
2395            reject_reason::Reason::DuplicateAggregationKey(v) => Self::DuplicateAggregationKey {
2396                contents: Box::new(v.try_into()?),
2397            },
2398            reject_reason::Reason::NonExistentCredentialId(_) => Self::NonExistentCredentialID,
2399            reject_reason::Reason::KeyIndexAlreadyInUse(_) => Self::KeyIndexAlreadyInUse,
2400            reject_reason::Reason::InvalidAccountThreshold(_) => Self::InvalidAccountThreshold,
2401            reject_reason::Reason::InvalidCredentialKeySignThreshold(_) => {
2402                Self::InvalidCredentialKeySignThreshold
2403            }
2404            reject_reason::Reason::InvalidEncryptedAmountTransferProof(_) => {
2405                Self::InvalidEncryptedAmountTransferProof
2406            }
2407            reject_reason::Reason::InvalidTransferToPublicProof(_) => {
2408                Self::InvalidTransferToPublicProof
2409            }
2410            reject_reason::Reason::EncryptedAmountSelfTransfer(v) => {
2411                Self::EncryptedAmountSelfTransfer {
2412                    contents: v.try_into()?,
2413                }
2414            }
2415            reject_reason::Reason::InvalidIndexOnEncryptedTransfer(_) => {
2416                Self::InvalidIndexOnEncryptedTransfer
2417            }
2418            reject_reason::Reason::ZeroScheduledAmount(_) => Self::ZeroScheduledAmount,
2419            reject_reason::Reason::NonIncreasingSchedule(_) => Self::NonIncreasingSchedule,
2420            reject_reason::Reason::FirstScheduledReleaseExpired(_) => {
2421                Self::FirstScheduledReleaseExpired
2422            }
2423            reject_reason::Reason::ScheduledSelfTransfer(v) => Self::ScheduledSelfTransfer {
2424                contents: v.try_into()?,
2425            },
2426            reject_reason::Reason::InvalidCredentials(_) => Self::InvalidCredentials,
2427            reject_reason::Reason::DuplicateCredIds(v) => Self::DuplicateCredIDs {
2428                contents: v
2429                    .ids
2430                    .into_iter()
2431                    .map(TryFrom::try_from)
2432                    .collect::<Result<_, tonic::Status>>()?,
2433            },
2434            reject_reason::Reason::NonExistentCredIds(v) => Self::NonExistentCredIDs {
2435                contents: v
2436                    .ids
2437                    .into_iter()
2438                    .map(TryFrom::try_from)
2439                    .collect::<Result<_, tonic::Status>>()?,
2440            },
2441            reject_reason::Reason::RemoveFirstCredential(_) => Self::RemoveFirstCredential,
2442            reject_reason::Reason::CredentialHolderDidNotSign(_) => {
2443                Self::CredentialHolderDidNotSign
2444            }
2445            reject_reason::Reason::NotAllowedMultipleCredentials(_) => {
2446                Self::NotAllowedMultipleCredentials
2447            }
2448            reject_reason::Reason::NotAllowedToReceiveEncrypted(_) => {
2449                Self::NotAllowedToReceiveEncrypted
2450            }
2451            reject_reason::Reason::NotAllowedToHandleEncrypted(_) => {
2452                Self::NotAllowedToHandleEncrypted
2453            }
2454            reject_reason::Reason::MissingBakerAddParameters(_) => Self::MissingBakerAddParameters,
2455            reject_reason::Reason::FinalizationRewardCommissionNotInRange(_) => {
2456                Self::FinalizationRewardCommissionNotInRange
2457            }
2458            reject_reason::Reason::BakingRewardCommissionNotInRange(_) => {
2459                Self::BakingRewardCommissionNotInRange
2460            }
2461            reject_reason::Reason::TransactionFeeCommissionNotInRange(_) => {
2462                Self::TransactionFeeCommissionNotInRange
2463            }
2464            reject_reason::Reason::AlreadyADelegator(_) => Self::AlreadyADelegator,
2465            reject_reason::Reason::InsufficientBalanceForDelegationStake(_) => {
2466                Self::InsufficientBalanceForDelegationStake
2467            }
2468            reject_reason::Reason::MissingDelegationAddParameters(_) => {
2469                Self::MissingDelegationAddParameters
2470            }
2471            reject_reason::Reason::InsufficientDelegationStake(_) => {
2472                Self::InsufficientDelegationStake
2473            }
2474            reject_reason::Reason::DelegatorInCooldown(_) => Self::DelegatorInCooldown,
2475            reject_reason::Reason::NotADelegator(v) => Self::NotADelegator {
2476                address: v.try_into()?,
2477            },
2478            reject_reason::Reason::DelegationTargetNotABaker(v) => {
2479                Self::DelegationTargetNotABaker { target: v.into() }
2480            }
2481            reject_reason::Reason::StakeOverMaximumThresholdForPool(_) => {
2482                Self::StakeOverMaximumThresholdForPool
2483            }
2484            reject_reason::Reason::PoolWouldBecomeOverDelegated(_) => {
2485                Self::PoolWouldBecomeOverDelegated
2486            }
2487            reject_reason::Reason::PoolClosed(_) => Self::PoolClosed,
2488            reject_reason::Reason::NonExistentTokenId(token_id) => Self::NonExistentTokenId {
2489                token_id: token_id.try_into()?,
2490            },
2491            reject_reason::Reason::TokenUpdateTransactionFailed(token_module_reject_reason) => {
2492                Self::TokenUpdateTransactionFailed {
2493                    reject_reason: token_module_reject_reason.try_into()?,
2494                }
2495            }
2496        })
2497    }
2498}
2499
2500impl TryFrom<NextAccountSequenceNumber> for super::types::queries::AccountNonceResponse {
2501    type Error = tonic::Status;
2502
2503    fn try_from(value: NextAccountSequenceNumber) -> Result<Self, Self::Error> {
2504        Ok(Self {
2505            nonce: value.sequence_number.require()?.into(),
2506            all_final: value.all_final,
2507        })
2508    }
2509}
2510
2511impl From<block_item_summary::TransactionIndex> for super::types::TransactionIndex {
2512    fn from(value: block_item_summary::TransactionIndex) -> Self {
2513        Self { index: value.value }
2514    }
2515}
2516
2517impl From<Energy> for super::types::Energy {
2518    fn from(value: Energy) -> Self {
2519        Self {
2520            energy: value.value,
2521        }
2522    }
2523}
2524
2525impl TryFrom<ConsensusInfo> for super::types::queries::ConsensusInfo {
2526    type Error = tonic::Status;
2527
2528    fn try_from(value: ConsensusInfo) -> Result<Self, Self::Error> {
2529        let protocol_version = protocol_version_int_from_enum(value.protocol_version)?;
2530        Ok(Self {
2531            last_finalized_block_height: value.last_finalized_block_height.require()?.into(),
2532            block_arrive_latency_e_m_s_d: value.block_arrive_latency_emsd,
2533            block_receive_latency_e_m_s_d: value.block_receive_latency_emsd,
2534            last_finalized_block: value.last_finalized_block.require()?.try_into()?,
2535            block_receive_period_e_m_s_d: value.block_receive_period_emsd,
2536            block_arrive_period_e_m_s_d: value.block_arrive_period_emsd,
2537            blocks_received_count: value.blocks_received_count.into(),
2538            transactions_per_block_e_m_s_d: value.transactions_per_block_emsd,
2539            finalization_period_e_m_a: value.finalization_period_ema,
2540            best_block_height: value.best_block_height.require()?.into(),
2541            last_finalized_time: value
2542                .last_finalized_time
2543                .map(|v| v.try_into())
2544                .transpose()?,
2545            finalization_count: value.finalization_count.into(),
2546            epoch_duration: value.epoch_duration.require()?.try_into()?,
2547            blocks_verified_count: value.blocks_verified_count.into(),
2548            slot_duration: value.slot_duration.map(Into::into),
2549            genesis_time: value.genesis_time.require()?.try_into()?,
2550            finalization_period_e_m_s_d: value.finalization_period_emsd,
2551            transactions_per_block_e_m_a: value.transactions_per_block_ema,
2552            block_arrive_latency_e_m_a: value.block_arrive_latency_ema,
2553            block_receive_latency_e_m_a: value.block_receive_latency_ema,
2554            block_arrive_period_e_m_a: value.block_arrive_period_ema,
2555            block_receive_period_e_m_a: value.block_receive_period_ema,
2556            block_last_arrived_time: value
2557                .block_last_arrived_time
2558                .map(|v| v.try_into())
2559                .transpose()?,
2560            best_block: value.best_block.require()?.try_into()?,
2561            genesis_block: value.genesis_block.require()?.try_into()?,
2562            block_last_received_time: value
2563                .block_last_received_time
2564                .map(|v| v.try_into())
2565                .transpose()?,
2566            protocol_version,
2567            genesis_index: value.genesis_index.require()?.into(),
2568            current_era_genesis_block: value.current_era_genesis_block.require()?.try_into()?,
2569            current_era_genesis_time: value.current_era_genesis_time.require()?.try_into()?,
2570            concordium_bft_status: if protocol_version <= super::types::ProtocolVersion::P5.into() {
2571                None
2572            } else {
2573                Some(ConcordiumBFTDetails {
2574                    current_timeout_duration: value
2575                        .current_timeout_duration
2576                        .require()?
2577                        .try_into()?,
2578                    current_round: value.current_round.require()?.into(),
2579                    current_epoch: value.current_epoch.require()?.into(),
2580                    trigger_block_time: value.trigger_block_time.require()?.try_into()?,
2581                })
2582            },
2583        })
2584    }
2585}
2586
2587impl TryFrom<InvokeInstanceResponse> for super::types::smart_contracts::InvokeContractResult {
2588    type Error = tonic::Status;
2589
2590    fn try_from(response: InvokeInstanceResponse) -> Result<Self, Self::Error> {
2591        use super::types::smart_contracts::{InvokeContractResult, ReturnValue};
2592        let result = match response.result.require()? {
2593            invoke_instance_response::Result::Failure(value) => InvokeContractResult::Failure {
2594                return_value: value.return_value.map(|b| ReturnValue { value: b }),
2595                reason: Upward::from(value.reason.map(TryFrom::try_from).transpose()?),
2596                used_energy: value.used_energy.require()?.into(),
2597            },
2598            invoke_instance_response::Result::Success(value) => InvokeContractResult::Success {
2599                return_value: value.return_value.map(|b| ReturnValue { value: b }),
2600                events: value
2601                    .effects
2602                    .into_iter()
2603                    .map(|trace| {
2604                        Ok(Upward::from(
2605                            trace
2606                                .element
2607                                .map(super::types::ContractTraceElement::try_from)
2608                                .transpose()?,
2609                        ))
2610                    })
2611                    .collect::<Result<_, tonic::Status>>()?,
2612                used_energy: value.used_energy.require()?.into(),
2613            },
2614        };
2615        Ok(result)
2616    }
2617}
2618
2619impl TryFrom<CryptographicParameters> for super::types::CryptographicParameters {
2620    type Error = tonic::Status;
2621
2622    fn try_from(value: CryptographicParameters) -> Result<Self, Self::Error> {
2623        Ok(Self {
2624            genesis_string: value.genesis_string,
2625            on_chain_commitment_key: concordium_base::common::from_bytes(
2626                &mut std::io::Cursor::new(&value.on_chain_commitment_key),
2627            )
2628            .map_err(|_| tonic::Status::internal("Invalid on_chain_commitment_key received"))?,
2629
2630            bulletproof_generators: concordium_base::common::from_bytes(&mut std::io::Cursor::new(
2631                &value.bulletproof_generators,
2632            ))
2633            .map_err(|_| tonic::Status::internal("Invalid bulletproof_generators received"))?,
2634        })
2635    }
2636}
2637
2638impl TryFrom<CredentialsPerBlockLimit> for super::types::CredentialsPerBlockLimit {
2639    type Error = tonic::Status;
2640
2641    fn try_from(value: CredentialsPerBlockLimit) -> Result<Self, Self::Error> {
2642        Ok(Self {
2643            limit: value.value.try_into().map_err(|_| {
2644                tonic::Status::internal("Unexpectedly large account creation limit")
2645            })?,
2646        })
2647    }
2648}
2649
2650impl TryFrom<TimeoutParameters> for chain_parameters::TimeoutParameters {
2651    type Error = tonic::Status;
2652
2653    fn try_from(value: TimeoutParameters) -> Result<Self, Self::Error> {
2654        Ok(Self {
2655            base: value.timeout_base.map(Into::into),
2656            increase: value.timeout_increase.map(TryInto::try_into).transpose()?,
2657            decrease: value.timeout_decrease.map(TryInto::try_into).transpose()?,
2658        })
2659    }
2660}
2661
2662impl From<CooldownParametersCpv1> for chain_parameters::CooldownParameters {
2663    fn from(value: CooldownParametersCpv1) -> Self {
2664        Self {
2665            baker_cooldown_epochs: None,
2666            pool_owner_cooldown: value.pool_owner_cooldown.map(Into::into),
2667            delegator_cooldown: value.delegator_cooldown.map(Into::into),
2668        }
2669    }
2670}
2671
2672impl From<MintDistributionCpv0> for chain_parameters::MintDistribution {
2673    fn from(value: MintDistributionCpv0) -> Self {
2674        Self {
2675            baking_reward: value.baking_reward.map(Into::into),
2676            finalization_reward: value.finalization_reward.map(Into::into),
2677        }
2678    }
2679}
2680
2681impl From<MintDistributionCpv1> for chain_parameters::MintDistribution {
2682    fn from(value: MintDistributionCpv1) -> Self {
2683        Self {
2684            baking_reward: value.baking_reward.map(Into::into),
2685            finalization_reward: value.finalization_reward.map(Into::into),
2686        }
2687    }
2688}
2689
2690impl From<TransactionFeeDistribution> for chain_parameters::TransactionFeeDistribution {
2691    fn from(value: TransactionFeeDistribution) -> Self {
2692        Self {
2693            baker: value.baker.map(Into::into),
2694            gas_account: value.gas_account.map(Into::into),
2695        }
2696    }
2697}
2698
2699impl From<GasRewards> for chain_parameters::GasRewards {
2700    fn from(value: GasRewards) -> Self {
2701        Self {
2702            baker: value.baker.map(Into::into),
2703            finalization_proof: value.finalization_proof.map(Into::into),
2704            account_creation: value.account_creation.map(Into::into),
2705            chain_update: value.chain_update.map(Into::into),
2706        }
2707    }
2708}
2709
2710impl From<GasRewardsCpv2> for chain_parameters::GasRewards {
2711    fn from(value: GasRewardsCpv2) -> Self {
2712        Self {
2713            baker: value.baker.map(Into::into),
2714            finalization_proof: None,
2715            account_creation: value.account_creation.map(Into::into),
2716            chain_update: value.chain_update.map(Into::into),
2717        }
2718    }
2719}
2720
2721impl TryFrom<PoolParametersCpv1> for chain_parameters::StakingParameters {
2722    type Error = tonic::Status;
2723
2724    fn try_from(value: PoolParametersCpv1) -> Result<Self, Self::Error> {
2725        Ok(Self {
2726            passive_finalization_commission: value.passive_finalization_commission.map(Into::into),
2727            passive_baking_commission: value.passive_baking_commission.map(Into::into),
2728            passive_transaction_commission: value.passive_transaction_commission.map(Into::into),
2729            finalization_commission_range: value
2730                .commission_bounds
2731                .as_ref()
2732                .and_then(|cb| cb.finalization.map(TryInto::try_into))
2733                .transpose()?,
2734            baking_commission_range: value
2735                .commission_bounds
2736                .as_ref()
2737                .and_then(|cb| cb.baking.map(TryInto::try_into))
2738                .transpose()?,
2739            transaction_commission_range: value
2740                .commission_bounds
2741                .as_ref()
2742                .and_then(|cb| cb.transaction.map(TryInto::try_into))
2743                .transpose()?,
2744            minimum_equity_capital: value.minimum_equity_capital.map(Into::into),
2745            capital_bound: value.capital_bound.map(TryInto::try_into).transpose()?,
2746            leverage_bound: value.leverage_bound.map(TryInto::try_into).transpose()?,
2747        })
2748    }
2749}
2750
2751impl From<FinalizationCommitteeParameters> for chain_parameters::FinalizationCommitteeParameters {
2752    fn from(value: FinalizationCommitteeParameters) -> Self {
2753        Self {
2754            min_finalizers: Some(value.minimum_finalizers),
2755            max_finalizers: Some(value.maximum_finalizers),
2756            finalizers_relative_stake_threshold: value
2757                .finalizer_relative_stake_threshold
2758                .map(Into::into),
2759        }
2760    }
2761}
2762
2763impl TryFrom<ChainParametersV0> for chain_parameters::ChainParameters {
2764    type Error = tonic::Status;
2765
2766    fn try_from(value: ChainParametersV0) -> Result<Self, Self::Error> {
2767        Ok(Self {
2768            timeout_parameters: Default::default(),
2769            election_difficulty: value
2770                .election_difficulty
2771                .map(TryInto::try_into)
2772                .transpose()?,
2773            min_block_time: None,
2774            block_energy_limit: None,
2775            euro_per_energy: value.euro_per_energy.map(TryInto::try_into).transpose()?,
2776            micro_ccd_per_euro: value
2777                .micro_ccd_per_euro
2778                .map(TryInto::try_into)
2779                .transpose()?,
2780            cooldown_parameters: value
2781                .baker_cooldown_epochs
2782                .map(|bce| chain_parameters::CooldownParameters {
2783                    baker_cooldown_epochs: Some(bce.into()),
2784                    pool_owner_cooldown: None,
2785                    delegator_cooldown: None,
2786                })
2787                .unwrap_or_default(),
2788            reward_period_length: None,
2789            mint_per_payday: None,
2790            mint_per_slot: value
2791                .mint_distribution
2792                .and_then(|md| md.mint_per_slot.map(TryInto::try_into))
2793                .transpose()?,
2794            mint_distribution: value.mint_distribution.map(Into::into).unwrap_or_default(),
2795            account_creation_limit: value
2796                .account_creation_limit
2797                .map(TryInto::try_into)
2798                .transpose()?,
2799            transaction_fee_distribution: value
2800                .transaction_fee_distribution
2801                .map(Into::into)
2802                .unwrap_or_default(),
2803            gas_rewards: value.gas_rewards.map(Into::into).unwrap_or_default(),
2804            foundation_account: value
2805                .foundation_account
2806                .map(TryInto::try_into)
2807                .transpose()?,
2808            staking_parameters: value
2809                .minimum_threshold_for_baking
2810                .map(|mtfb| chain_parameters::StakingParameters {
2811                    minimum_equity_capital: Some(mtfb.into()),
2812                    ..Default::default()
2813                })
2814                .unwrap_or_default(),
2815            finalization_committee_parameters: Default::default(),
2816            validator_max_missed_rounds: None,
2817
2818            keys: chain_parameters::UpdateKeys {
2819                root_keys: value.root_keys.map(TryInto::try_into).transpose()?,
2820                level_1_keys: value.level1_keys.map(TryInto::try_into).transpose()?,
2821                level_2_keys: value.level2_keys.map(TryInto::try_into).transpose()?,
2822            },
2823        })
2824    }
2825}
2826
2827impl TryFrom<ChainParametersV1> for chain_parameters::ChainParameters {
2828    type Error = tonic::Status;
2829
2830    fn try_from(value: ChainParametersV1) -> Result<Self, Self::Error> {
2831        Ok(Self {
2832            timeout_parameters: Default::default(),
2833            election_difficulty: value
2834                .election_difficulty
2835                .map(TryInto::try_into)
2836                .transpose()?,
2837            min_block_time: None,
2838            block_energy_limit: None,
2839            euro_per_energy: value.euro_per_energy.map(TryInto::try_into).transpose()?,
2840            micro_ccd_per_euro: value
2841                .micro_ccd_per_euro
2842                .map(TryInto::try_into)
2843                .transpose()?,
2844            cooldown_parameters: value
2845                .cooldown_parameters
2846                .map(Into::into)
2847                .unwrap_or_default(),
2848            reward_period_length: value
2849                .time_parameters
2850                .as_ref()
2851                .and_then(|tp| tp.reward_period_length.map(TryInto::try_into))
2852                .transpose()?,
2853            mint_per_payday: value
2854                .time_parameters
2855                .as_ref()
2856                .and_then(|tp| tp.mint_per_payday.map(TryInto::try_into))
2857                .transpose()?,
2858            mint_per_slot: None,
2859            account_creation_limit: value
2860                .account_creation_limit
2861                .map(TryInto::try_into)
2862                .transpose()?,
2863            mint_distribution: value.mint_distribution.map(Into::into).unwrap_or_default(),
2864            transaction_fee_distribution: value
2865                .transaction_fee_distribution
2866                .map(Into::into)
2867                .unwrap_or_default(),
2868            gas_rewards: value.gas_rewards.map(Into::into).unwrap_or_default(),
2869            foundation_account: value
2870                .foundation_account
2871                .map(TryInto::try_into)
2872                .transpose()?,
2873            staking_parameters: value
2874                .pool_parameters
2875                .map(TryInto::try_into)
2876                .transpose()?
2877                .unwrap_or_default(),
2878            finalization_committee_parameters: Default::default(),
2879            validator_max_missed_rounds: None,
2880            keys: chain_parameters::UpdateKeys {
2881                root_keys: value.root_keys.map(TryInto::try_into).transpose()?,
2882                level_1_keys: value.level1_keys.map(TryInto::try_into).transpose()?,
2883                level_2_keys: value.level2_keys.map(TryInto::try_into).transpose()?,
2884            },
2885        })
2886    }
2887}
2888
2889impl TryFrom<ChainParametersV2> for chain_parameters::ChainParameters {
2890    type Error = tonic::Status;
2891
2892    fn try_from(value: ChainParametersV2) -> Result<Self, Self::Error> {
2893        Ok(Self {
2894            timeout_parameters: value
2895                .consensus_parameters
2896                .as_ref()
2897                .and_then(|cp| cp.timeout_parameters.map(TryInto::try_into))
2898                .transpose()?
2899                .unwrap_or_default(),
2900            election_difficulty: None,
2901            min_block_time: value
2902                .consensus_parameters
2903                .as_ref()
2904                .and_then(|cp| cp.min_block_time.map(Into::into)),
2905            block_energy_limit: value
2906                .consensus_parameters
2907                .as_ref()
2908                .and_then(|cp| cp.block_energy_limit.map(Into::into)),
2909            euro_per_energy: value.euro_per_energy.map(TryInto::try_into).transpose()?,
2910            micro_ccd_per_euro: value
2911                .micro_ccd_per_euro
2912                .map(TryInto::try_into)
2913                .transpose()?,
2914            cooldown_parameters: value
2915                .cooldown_parameters
2916                .map(Into::into)
2917                .unwrap_or_default(),
2918            reward_period_length: value
2919                .time_parameters
2920                .as_ref()
2921                .and_then(|tp| tp.reward_period_length.map(TryInto::try_into))
2922                .transpose()?,
2923            mint_per_payday: value
2924                .time_parameters
2925                .as_ref()
2926                .and_then(|tp| tp.mint_per_payday.map(TryInto::try_into))
2927                .transpose()?,
2928            mint_per_slot: None,
2929            account_creation_limit: value
2930                .account_creation_limit
2931                .map(TryInto::try_into)
2932                .transpose()?,
2933            mint_distribution: value.mint_distribution.map(Into::into).unwrap_or_default(),
2934            transaction_fee_distribution: value
2935                .transaction_fee_distribution
2936                .map(Into::into)
2937                .unwrap_or_default(),
2938            gas_rewards: value.gas_rewards.map(Into::into).unwrap_or_default(),
2939            foundation_account: value
2940                .foundation_account
2941                .map(TryInto::try_into)
2942                .transpose()?,
2943            staking_parameters: value
2944                .pool_parameters
2945                .map(TryInto::try_into)
2946                .transpose()?
2947                .unwrap_or_default(),
2948            finalization_committee_parameters: value
2949                .finalization_committee_parameters
2950                .map(Into::into)
2951                .unwrap_or_default(),
2952            validator_max_missed_rounds: None,
2953            keys: chain_parameters::UpdateKeys {
2954                root_keys: value.root_keys.map(TryInto::try_into).transpose()?,
2955                level_1_keys: value.level1_keys.map(TryInto::try_into).transpose()?,
2956                level_2_keys: value.level2_keys.map(TryInto::try_into).transpose()?,
2957            },
2958        })
2959    }
2960}
2961
2962impl TryFrom<ChainParametersV3> for chain_parameters::ChainParameters {
2963    type Error = tonic::Status;
2964
2965    fn try_from(value: ChainParametersV3) -> Result<Self, Self::Error> {
2966        Ok(Self {
2967            timeout_parameters: value
2968                .consensus_parameters
2969                .as_ref()
2970                .and_then(|cp| cp.timeout_parameters.map(TryInto::try_into))
2971                .transpose()?
2972                .unwrap_or_default(),
2973            election_difficulty: None,
2974            min_block_time: value
2975                .consensus_parameters
2976                .as_ref()
2977                .and_then(|cp| cp.min_block_time.map(Into::into)),
2978            block_energy_limit: value
2979                .consensus_parameters
2980                .as_ref()
2981                .and_then(|cp| cp.block_energy_limit.map(Into::into)),
2982            euro_per_energy: value.euro_per_energy.map(TryInto::try_into).transpose()?,
2983            micro_ccd_per_euro: value
2984                .micro_ccd_per_euro
2985                .map(TryInto::try_into)
2986                .transpose()?,
2987            cooldown_parameters: value
2988                .cooldown_parameters
2989                .map(Into::into)
2990                .unwrap_or_default(),
2991            reward_period_length: value
2992                .time_parameters
2993                .as_ref()
2994                .and_then(|tp| tp.reward_period_length.map(TryInto::try_into))
2995                .transpose()?,
2996            mint_per_payday: value
2997                .time_parameters
2998                .as_ref()
2999                .and_then(|tp| tp.mint_per_payday.map(TryInto::try_into))
3000                .transpose()?,
3001            mint_per_slot: None,
3002            account_creation_limit: value
3003                .account_creation_limit
3004                .map(TryInto::try_into)
3005                .transpose()?,
3006            mint_distribution: value.mint_distribution.map(Into::into).unwrap_or_default(),
3007            transaction_fee_distribution: value
3008                .transaction_fee_distribution
3009                .map(Into::into)
3010                .unwrap_or_default(),
3011            gas_rewards: value.gas_rewards.map(Into::into).unwrap_or_default(),
3012            foundation_account: value
3013                .foundation_account
3014                .map(TryInto::try_into)
3015                .transpose()?,
3016            staking_parameters: value
3017                .pool_parameters
3018                .map(TryInto::try_into)
3019                .transpose()?
3020                .unwrap_or_default(),
3021            finalization_committee_parameters: value
3022                .finalization_committee_parameters
3023                .map(Into::into)
3024                .unwrap_or_default(),
3025            validator_max_missed_rounds: value
3026                .validator_score_parameters
3027                .map(|vsp| vsp.maximum_missed_rounds),
3028            keys: chain_parameters::UpdateKeys {
3029                root_keys: value.root_keys.map(TryInto::try_into).transpose()?,
3030                level_1_keys: value.level1_keys.map(TryInto::try_into).transpose()?,
3031                level_2_keys: value.level2_keys.map(TryInto::try_into).transpose()?,
3032            },
3033        })
3034    }
3035}
3036
3037impl TryFrom<ChainParameters> for chain_parameters::ChainParameters {
3038    type Error = tonic::Status;
3039
3040    fn try_from(value: ChainParameters) -> Result<Self, Self::Error> {
3041        match value.parameters.require()? {
3042            generated::chain_parameters::Parameters::V0(v0) => v0.try_into(),
3043            generated::chain_parameters::Parameters::V1(v1) => v1.try_into(),
3044            generated::chain_parameters::Parameters::V2(v2) => v2.try_into(),
3045            generated::chain_parameters::Parameters::V3(v3) => v3.try_into(),
3046        }
3047    }
3048}
3049
3050impl TryFrom<FinalizationSummaryParty> for super::types::FinalizationSummaryParty {
3051    type Error = tonic::Status;
3052
3053    fn try_from(value: FinalizationSummaryParty) -> Result<Self, Self::Error> {
3054        Ok(Self {
3055            baker_id: value.baker.require()?.into(),
3056            weight: value.weight,
3057            signed: value.signed,
3058        })
3059    }
3060}
3061
3062impl From<FinalizationIndex> for super::types::FinalizationIndex {
3063    fn from(value: FinalizationIndex) -> Self {
3064        value.value.into()
3065    }
3066}
3067
3068impl TryFrom<BlockFinalizationSummary> for Option<super::types::FinalizationSummary> {
3069    type Error = tonic::Status;
3070
3071    fn try_from(value: BlockFinalizationSummary) -> Result<Self, Self::Error> {
3072        match value.summary.require()? {
3073            block_finalization_summary::Summary::None(_) => Ok(None),
3074            block_finalization_summary::Summary::Record(r) => {
3075                Ok(Some(super::types::FinalizationSummary {
3076                    block_pointer: r.block.require()?.try_into()?,
3077                    index: r.index.require()?.into(),
3078                    delay: r.delay.require()?.into(),
3079                    finalizers: r
3080                        .finalizers
3081                        .into_iter()
3082                        .map(super::types::FinalizationSummaryParty::try_from)
3083                        .collect::<Result<_, tonic::Status>>()?,
3084                }))
3085            }
3086        }
3087    }
3088}
3089
3090impl TryFrom<BlockInfo> for super::types::queries::BlockInfo {
3091    type Error = tonic::Status;
3092
3093    fn try_from(value: BlockInfo) -> Result<Self, Self::Error> {
3094        let protocol_version = protocol_version_int_from_enum(value.protocol_version)?;
3095
3096        Ok(Self {
3097            transactions_size: value.transactions_size.into(),
3098            block_parent: value.parent_block.require()?.try_into()?,
3099            block_hash: value.hash.require()?.try_into()?,
3100            finalized: value.finalized,
3101            block_state_hash: value.state_hash.require()?.try_into()?,
3102            block_arrive_time: value.arrive_time.require()?.try_into()?,
3103            block_receive_time: value.receive_time.require()?.try_into()?,
3104            transaction_count: value.transaction_count.into(),
3105            transaction_energy_cost: value.transactions_energy_cost.require()?.into(),
3106            block_slot: if protocol_version <= super::types::ProtocolVersion::P5.into() {
3107                Some(value.slot_number.require()?.into())
3108            } else {
3109                None
3110            },
3111            block_last_finalized: value.last_finalized_block.require()?.try_into()?,
3112            block_slot_time: value.slot_time.require()?.try_into()?,
3113            block_height: value.height.require()?.into(),
3114            era_block_height: value.era_block_height.require()?.into(),
3115            genesis_index: value.genesis_index.require()?.into(),
3116            block_baker: value.baker.map(|b| b.into()),
3117            protocol_version,
3118            round: if protocol_version >= super::types::ProtocolVersion::P6.into() {
3119                Some(value.round.require()?.into())
3120            } else {
3121                None
3122            },
3123            epoch: if protocol_version >= super::types::ProtocolVersion::P6.into() {
3124                Some(value.epoch.require()?.into())
3125            } else {
3126                None
3127            },
3128        })
3129    }
3130}
3131
3132impl TryFrom<PoolInfoResponse> for super::types::BakerPoolStatus {
3133    type Error = tonic::Status;
3134
3135    fn try_from(value: PoolInfoResponse) -> Result<Self, Self::Error> {
3136        // The active baker pool status is present iff the pool info is present in the
3137        // response.
3138        let active_baker_pool_status = match value.pool_info {
3139            None => None,
3140            Some(pi) => Some(ActiveBakerPoolStatus {
3141                baker_equity_capital: value.equity_capital.require()?.into(),
3142                delegated_capital: value.delegated_capital.require()?.into(),
3143                delegated_capital_cap: value.delegated_capital_cap.require()?.into(),
3144                pool_info: pi.try_into()?,
3145                baker_stake_pending_change: value.equity_pending_change.try_into()?,
3146            }),
3147        };
3148
3149        Ok(Self {
3150            baker_id: value.baker.require()?.into(),
3151            baker_address: value.address.require()?.try_into()?,
3152            active_baker_pool_status,
3153            current_payday_status: if let Some(v) = value.current_payday_info {
3154                Some(v.try_into()?)
3155            } else {
3156                None
3157            },
3158            all_pool_total_capital: value.all_pool_total_capital.require()?.into(),
3159        })
3160    }
3161}
3162
3163impl TryFrom<Option<PoolPendingChange>> for super::types::PoolPendingChange {
3164    type Error = tonic::Status;
3165
3166    fn try_from(value: Option<PoolPendingChange>) -> Result<Self, Self::Error> {
3167        if let Some(value) = value {
3168            match value.change.require()? {
3169                pool_pending_change::Change::Reduce(rs) => Ok(Self::ReduceBakerCapital {
3170                    baker_equity_capital: rs.reduced_equity_capital.require()?.into(),
3171                    effective_time: rs.effective_time.require()?.try_into()?,
3172                }),
3173                pool_pending_change::Change::Remove(rs) => Ok(Self::RemovePool {
3174                    effective_time: rs.effective_time.require()?.try_into()?,
3175                }),
3176            }
3177        } else {
3178            Ok(Self::NoChange)
3179        }
3180    }
3181}
3182
3183impl TryFrom<PoolCurrentPaydayInfo> for super::types::CurrentPaydayBakerPoolStatus {
3184    type Error = tonic::Status;
3185
3186    fn try_from(value: PoolCurrentPaydayInfo) -> Result<Self, Self::Error> {
3187        Ok(Self {
3188            blocks_baked: value.blocks_baked,
3189            finalization_live: value.finalization_live,
3190            transaction_fees_earned: value.transaction_fees_earned.require()?.into(),
3191            effective_stake: value.effective_stake.require()?.into(),
3192            lottery_power: value.lottery_power,
3193            baker_equity_capital: value.baker_equity_capital.require()?.into(),
3194            delegated_capital: value.delegated_capital.require()?.into(),
3195            commission_rates: value.commission_rates.require()?.try_into()?,
3196        })
3197    }
3198}
3199
3200impl TryFrom<PassiveDelegationInfo> for super::types::PassiveDelegationStatus {
3201    type Error = tonic::Status;
3202
3203    fn try_from(value: PassiveDelegationInfo) -> Result<Self, Self::Error> {
3204        Ok(Self {
3205            delegated_capital: value.delegated_capital.require()?.into(),
3206            commission_rates: value.commission_rates.require()?.try_into()?,
3207            current_payday_transaction_fees_earned: value
3208                .current_payday_transaction_fees_earned
3209                .require()?
3210                .into(),
3211            current_payday_delegated_capital: value
3212                .current_payday_delegated_capital
3213                .require()?
3214                .into(),
3215            all_pool_total_capital: value.all_pool_total_capital.require()?.into(),
3216        })
3217    }
3218}
3219
3220impl From<&super::endpoints::BlocksAtHeightInput> for BlocksAtHeightRequest {
3221    fn from(&input: &super::endpoints::BlocksAtHeightInput) -> Self {
3222        let blocks_at_height = match input {
3223            super::endpoints::BlocksAtHeightInput::Absolute { height } => {
3224                blocks_at_height_request::BlocksAtHeight::Absolute(
3225                    blocks_at_height_request::Absolute {
3226                        height: Some(height.into()),
3227                    },
3228                )
3229            }
3230
3231            super::endpoints::BlocksAtHeightInput::Relative {
3232                height,
3233                genesis_index,
3234                restrict,
3235            } => blocks_at_height_request::BlocksAtHeight::Relative(
3236                blocks_at_height_request::Relative {
3237                    height: Some(height.into()),
3238                    genesis_index: Some(genesis_index.into()),
3239                    restrict,
3240                },
3241            ),
3242        };
3243        BlocksAtHeightRequest {
3244            blocks_at_height: Some(blocks_at_height),
3245        }
3246    }
3247}
3248
3249impl TryFrom<TokenomicsInfo> for super::types::RewardsOverview {
3250    type Error = tonic::Status;
3251
3252    fn try_from(value: TokenomicsInfo) -> Result<Self, Self::Error> {
3253        match value.tokenomics.require()? {
3254            tokenomics_info::Tokenomics::V0(value) => Ok(Self::V0 {
3255                data: super::types::CommonRewardData {
3256                    protocol_version: protocol_version_int_from_enum(value.protocol_version)?,
3257                    total_amount: value.total_amount.require()?.into(),
3258                    total_encrypted_amount: value.total_encrypted_amount.require()?.into(),
3259                    baking_reward_account: value.baking_reward_account.require()?.into(),
3260                    finalization_reward_account: value
3261                        .finalization_reward_account
3262                        .require()?
3263                        .into(),
3264                    gas_account: value.gas_account.require()?.into(),
3265                },
3266            }),
3267            tokenomics_info::Tokenomics::V1(value) => Ok(Self::V1 {
3268                common: super::types::CommonRewardData {
3269                    protocol_version: protocol_version_int_from_enum(value.protocol_version)?,
3270                    total_amount: value.total_amount.require()?.into(),
3271                    total_encrypted_amount: value.total_encrypted_amount.require()?.into(),
3272                    baking_reward_account: value.baking_reward_account.require()?.into(),
3273                    finalization_reward_account: value
3274                        .finalization_reward_account
3275                        .require()?
3276                        .into(),
3277                    gas_account: value.gas_account.require()?.into(),
3278                },
3279                foundation_transaction_rewards: value
3280                    .foundation_transaction_rewards
3281                    .require()?
3282                    .into(),
3283                next_payday_time: value.next_payday_time.require()?.try_into()?,
3284                next_payday_mint_rate: value.next_payday_mint_rate.require()?.try_into()?,
3285                total_staked_capital: value.total_staked_capital.require()?.into(),
3286            }),
3287        }
3288    }
3289}
3290
3291impl TryFrom<Branch> for super::types::queries::Branch {
3292    type Error = tonic::Status;
3293
3294    fn try_from(value: Branch) -> Result<Self, Self::Error> {
3295        // Tracking the branches which to visit next.
3296        let mut next = Vec::new();
3297        // For building a depth first search order of the tree.
3298        let mut dfs = Vec::new();
3299
3300        // First we build a depth first search order of the tree.
3301        next.extend(value.children.iter());
3302        dfs.push(&value);
3303        while let Some(value) = next.pop() {
3304            dfs.push(value);
3305            next.extend(value.children.iter());
3306        }
3307
3308        // Using depth first we build the new tree.
3309        let mut nodes = Vec::new();
3310        while let Some(value) = dfs.pop() {
3311            let mut children = Vec::new();
3312            for _ in 0..value.children.len() {
3313                // If a node have children, they should already be pushed and this is safe.
3314                children.push(nodes.pop().require()?);
3315            }
3316
3317            let node = Self {
3318                block_hash: value.block_hash.clone().require()?.try_into()?,
3319                children,
3320            };
3321            nodes.push(node)
3322        }
3323
3324        // Only one node should be left and is the root of the tree.
3325        let root = nodes.pop().require()?;
3326        Ok(root)
3327    }
3328}
3329
3330impl TryFrom<election_info::Baker> for super::types::BirkBaker {
3331    type Error = tonic::Status;
3332
3333    fn try_from(info: election_info::Baker) -> Result<Self, Self::Error> {
3334        Ok(Self {
3335            baker_id: info.baker.require()?.into(),
3336            baker_lottery_power: info.lottery_power,
3337            baker_account: info.account.require()?.try_into()?,
3338        })
3339    }
3340}
3341
3342impl TryFrom<ElectionInfo> for super::types::BirkParameters {
3343    type Error = tonic::Status;
3344
3345    fn try_from(info: ElectionInfo) -> Result<Self, Self::Error> {
3346        Ok(Self {
3347            election_difficulty: info.election_difficulty.map(|x| x.try_into()).transpose()?,
3348            election_nonce: info.election_nonce.require()?.try_into()?,
3349            bakers: info
3350                .baker_election_info
3351                .into_iter()
3352                .map(|c| c.try_into())
3353                .collect::<Result<_, _>>()?,
3354        })
3355    }
3356}
3357
3358impl TryFrom<block_special_event::AccountAmounts>
3359    for BTreeMap<super::AccountAddress, super::Amount>
3360{
3361    type Error = tonic::Status;
3362
3363    fn try_from(message: block_special_event::AccountAmounts) -> Result<Self, Self::Error> {
3364        fn mapper(
3365            entry: block_special_event::account_amounts::Entry,
3366        ) -> Result<(super::AccountAddress, super::Amount), tonic::Status> {
3367            Ok((
3368                entry.account.require()?.try_into()?,
3369                entry.amount.require()?.into(),
3370            ))
3371        }
3372
3373        message
3374            .entries
3375            .into_iter()
3376            .map(mapper)
3377            .collect::<Result<_, _>>()
3378    }
3379}
3380
3381impl TryFrom<block_special_event::Event> for super::types::SpecialTransactionOutcome {
3382    type Error = tonic::Status;
3383
3384    fn try_from(special_event: block_special_event::Event) -> Result<Self, Self::Error> {
3385        let event = match special_event {
3386            block_special_event::Event::BakingRewards(event) => Self::BakingRewards {
3387                baker_rewards: event.baker_rewards.require()?.try_into()?,
3388                remainder: event.remainder.require()?.into(),
3389            },
3390            block_special_event::Event::Mint(event) => Self::Mint {
3391                mint_baking_reward: event.mint_baking_reward.require()?.into(),
3392                mint_finalization_reward: event.mint_finalization_reward.require()?.into(),
3393                mint_platform_development_charge: event
3394                    .mint_platform_development_charge
3395                    .require()?
3396                    .into(),
3397                foundation_account: event.foundation_account.require()?.try_into()?,
3398            },
3399            block_special_event::Event::FinalizationRewards(event) => Self::FinalizationRewards {
3400                finalization_rewards: event.finalization_rewards.require()?.try_into()?,
3401                remainder: event.remainder.require()?.into(),
3402            },
3403            block_special_event::Event::BlockReward(event) => Self::BlockReward {
3404                transaction_fees: event.transaction_fees.require()?.into(),
3405                old_gas_account: event.old_gas_account.require()?.into(),
3406                new_gas_account: event.new_gas_account.require()?.into(),
3407                baker_reward: event.baker_reward.require()?.into(),
3408                foundation_charge: event.foundation_charge.require()?.into(),
3409                baker: event.baker.require()?.try_into()?,
3410                foundation_account: event.foundation_account.require()?.try_into()?,
3411            },
3412            block_special_event::Event::PaydayFoundationReward(event) => {
3413                Self::PaydayFoundationReward {
3414                    foundation_account: event.foundation_account.require()?.try_into()?,
3415                    development_charge: event.development_charge.require()?.into(),
3416                }
3417            }
3418            block_special_event::Event::PaydayAccountReward(event) => Self::PaydayAccountReward {
3419                account: event.account.require()?.try_into()?,
3420                transaction_fees: event.transaction_fees.require()?.into(),
3421                baker_reward: event.baker_reward.require()?.into(),
3422                finalization_reward: event.finalization_reward.require()?.into(),
3423            },
3424            block_special_event::Event::BlockAccrueReward(event) => Self::BlockAccrueReward {
3425                transaction_fees: event.transaction_fees.require()?.into(),
3426                old_gas_account: event.old_gas_account.require()?.into(),
3427                new_gas_account: event.new_gas_account.require()?.into(),
3428                baker_reward: event.baker_reward.require()?.into(),
3429                passive_reward: event.passive_reward.require()?.into(),
3430                foundation_charge: event.foundation_charge.require()?.into(),
3431                baker_id: event.baker.require()?.into(),
3432            },
3433            block_special_event::Event::PaydayPoolReward(event) => Self::PaydayPoolReward {
3434                pool_owner: event.pool_owner.map(|b| b.into()),
3435                transaction_fees: event.transaction_fees.require()?.into(),
3436                baker_reward: event.baker_reward.require()?.into(),
3437                finalization_reward: event.finalization_reward.require()?.into(),
3438            },
3439            block_special_event::Event::ValidatorSuspended(event) => Self::ValidatorSuspended {
3440                baker_id: event.baker_id.require()?.into(),
3441                account: event.account.require()?.try_into()?,
3442            },
3443            block_special_event::Event::ValidatorPrimedForSuspension(event) => {
3444                Self::ValidatorPrimedForSuspension {
3445                    baker_id: event.baker_id.require()?.into(),
3446                    account: event.account.require()?.try_into()?,
3447                }
3448            }
3449        };
3450        Ok(event)
3451    }
3452}
3453
3454impl TryFrom<BlockSpecialEvent> for Upward<super::types::SpecialTransactionOutcome> {
3455    type Error = tonic::Status;
3456
3457    fn try_from(message: BlockSpecialEvent) -> Result<Self, Self::Error> {
3458        let event = message
3459            .event
3460            .map(super::types::SpecialTransactionOutcome::try_from)
3461            .transpose()?;
3462        Ok(Upward::from(event))
3463    }
3464}
3465
3466impl<K> TryFrom<HigherLevelKeys> for updates::HigherLevelAccessStructure<K> {
3467    type Error = tonic::Status;
3468
3469    fn try_from(message: HigherLevelKeys) -> Result<Self, Self::Error> {
3470        Ok(Self {
3471            keys: message
3472                .keys
3473                .into_iter()
3474                .map(TryFrom::try_from)
3475                .collect::<Result<_, _>>()?,
3476            threshold: message.threshold.require()?.try_into()?,
3477            _phantom: Default::default(),
3478        })
3479    }
3480}
3481
3482impl TryFrom<ProtocolUpdate> for updates::ProtocolUpdate {
3483    type Error = tonic::Status;
3484
3485    fn try_from(value: ProtocolUpdate) -> Result<Self, Self::Error> {
3486        let message = value.message;
3487        let specification_url = value.specification_url;
3488        let specification_hash = value.specification_hash.require()?.try_into()?;
3489        let specification_auxiliary_data = value.specification_auxiliary_data;
3490        Ok(Self {
3491            message,
3492            specification_url,
3493            specification_hash,
3494            specification_auxiliary_data,
3495        })
3496    }
3497}
3498
3499impl TryFrom<ExchangeRate> for base::ExchangeRate {
3500    type Error = tonic::Status;
3501
3502    fn try_from(value: ExchangeRate) -> Result<Self, Self::Error> {
3503        let ratio = value.value.require()?;
3504        Self::new(ratio.numerator, ratio.denominator)
3505            .ok_or_else(|| tonic::Status::internal("Not a valid exchange rate."))
3506    }
3507}
3508
3509impl TryFrom<MintDistributionCpv0> for base::MintDistributionV0 {
3510    type Error = tonic::Status;
3511
3512    fn try_from(value: MintDistributionCpv0) -> Result<Self, Self::Error> {
3513        Ok(Self {
3514            mint_per_slot: value.mint_per_slot.require()?.try_into()?,
3515            baking_reward: value.baking_reward.require()?.into(),
3516            finalization_reward: value.finalization_reward.require()?.into(),
3517        })
3518    }
3519}
3520
3521impl TryFrom<MintDistributionCpv1> for base::MintDistributionV1 {
3522    type Error = tonic::Status;
3523
3524    fn try_from(value: MintDistributionCpv1) -> Result<Self, Self::Error> {
3525        Ok(Self {
3526            baking_reward: value.baking_reward.require()?.into(),
3527            finalization_reward: value.finalization_reward.require()?.into(),
3528        })
3529    }
3530}
3531
3532impl TryFrom<TransactionFeeDistribution> for updates::TransactionFeeDistribution {
3533    type Error = tonic::Status;
3534
3535    fn try_from(value: TransactionFeeDistribution) -> Result<Self, Self::Error> {
3536        Ok(Self {
3537            baker: value.baker.require()?.into(),
3538            gas_account: value.gas_account.require()?.into(),
3539        })
3540    }
3541}
3542
3543impl TryFrom<GasRewards> for updates::GASRewards {
3544    type Error = tonic::Status;
3545
3546    fn try_from(value: GasRewards) -> Result<Self, Self::Error> {
3547        Ok(Self {
3548            baker: value.baker.require()?.into(),
3549            finalization_proof: value.finalization_proof.require()?.into(),
3550            account_creation: value.account_creation.require()?.into(),
3551            chain_update: value.chain_update.require()?.into(),
3552        })
3553    }
3554}
3555
3556impl TryFrom<GasRewardsCpv2> for updates::GASRewardsV1 {
3557    type Error = tonic::Status;
3558
3559    fn try_from(value: GasRewardsCpv2) -> Result<Self, Self::Error> {
3560        Ok(Self {
3561            baker: value.baker.require()?.into(),
3562            account_creation: value.account_creation.require()?.into(),
3563            chain_update: value.chain_update.require()?.into(),
3564        })
3565    }
3566}
3567
3568impl TryFrom<TimeoutParameters> for updates::TimeoutParameters {
3569    type Error = tonic::Status;
3570
3571    fn try_from(value: TimeoutParameters) -> Result<Self, Self::Error> {
3572        let base = value.timeout_base.require()?.into();
3573        let increase = value.timeout_increase.require()?.try_into()?;
3574        let decrease = value.timeout_decrease.require()?.try_into()?;
3575        Self::new(base, increase, decrease).map_err(|err| tonic::Status::internal(err.to_string()))
3576    }
3577}
3578
3579impl TryFrom<Ratio> for concordium_base::common::types::Ratio {
3580    type Error = tonic::Status;
3581
3582    fn try_from(value: Ratio) -> Result<Self, Self::Error> {
3583        Self::new(value.numerator, value.denominator)
3584            .map_err(|err| tonic::Status::internal(err.to_string()))
3585    }
3586}
3587
3588impl TryFrom<FinalizationCommitteeParameters> for updates::FinalizationCommitteeParameters {
3589    type Error = tonic::Status;
3590
3591    fn try_from(value: FinalizationCommitteeParameters) -> Result<Self, Self::Error> {
3592        Ok(Self {
3593            min_finalizers: value.minimum_finalizers,
3594            max_finalizers: value.maximum_finalizers,
3595            finalizers_relative_stake_threshold: value
3596                .finalizer_relative_stake_threshold
3597                .require()?
3598                .into(),
3599        })
3600    }
3601}
3602
3603impl TryFrom<ValidatorScoreParameters> for updates::ValidatorScoreParameters {
3604    type Error = tonic::Status;
3605
3606    fn try_from(value: ValidatorScoreParameters) -> Result<Self, Self::Error> {
3607        Ok(Self {
3608            max_missed_rounds: value.maximum_missed_rounds,
3609        })
3610    }
3611}
3612
3613impl TryFrom<PoolParametersCpv1> for updates::PoolParameters {
3614    type Error = tonic::Status;
3615
3616    fn try_from(value: PoolParametersCpv1) -> Result<Self, Self::Error> {
3617        Ok(Self {
3618            passive_finalization_commission: value
3619                .passive_finalization_commission
3620                .require()?
3621                .into(),
3622            passive_baking_commission: value.passive_baking_commission.require()?.into(),
3623            passive_transaction_commission: value.passive_transaction_commission.require()?.into(),
3624            commission_bounds: value.commission_bounds.require()?.try_into()?,
3625            minimum_equity_capital: value.minimum_equity_capital.require()?.into(),
3626            capital_bound: value.capital_bound.require()?.try_into()?,
3627            leverage_bound: value.leverage_bound.require()?.try_into()?,
3628        })
3629    }
3630}
3631
3632impl TryFrom<LeverageFactor> for super::types::LeverageFactor {
3633    type Error = tonic::Status;
3634
3635    fn try_from(value: LeverageFactor) -> Result<Self, Self::Error> {
3636        let ratio = value.value.require()?;
3637        Self::new(ratio.numerator, ratio.denominator)
3638            .ok_or_else(|| tonic::Status::internal("Invalid leverage factor."))
3639    }
3640}
3641
3642impl TryFrom<CommissionRanges> for super::types::CommissionRanges {
3643    type Error = tonic::Status;
3644
3645    fn try_from(value: CommissionRanges) -> Result<Self, Self::Error> {
3646        Ok(Self {
3647            finalization: value.finalization.require()?.try_into()?,
3648            baking: value.baking.require()?.try_into()?,
3649            transaction: value.transaction.require()?.try_into()?,
3650        })
3651    }
3652}
3653
3654impl TryFrom<BakerStakeThreshold> for updates::BakerParameters {
3655    type Error = tonic::Status;
3656
3657    fn try_from(value: BakerStakeThreshold) -> Result<Self, Self::Error> {
3658        Ok(Self {
3659            minimum_threshold_for_baking: value.baker_stake_threshold.require()?.into(),
3660        })
3661    }
3662}
3663
3664impl TryFrom<CooldownParametersCpv1> for updates::CooldownParameters {
3665    type Error = tonic::Status;
3666
3667    fn try_from(value: CooldownParametersCpv1) -> Result<Self, Self::Error> {
3668        Ok(Self {
3669            pool_owner_cooldown: value.pool_owner_cooldown.require()?.into(),
3670            delegator_cooldown: value.delegator_cooldown.require()?.into(),
3671        })
3672    }
3673}
3674
3675impl TryFrom<TimeParametersCpv1> for updates::TimeParameters {
3676    type Error = tonic::Status;
3677
3678    fn try_from(value: TimeParametersCpv1) -> Result<Self, Self::Error> {
3679        Ok(Self {
3680            reward_period_length: value.reward_period_length.require()?.try_into()?,
3681            mint_per_payday: value.mint_per_payday.require()?.try_into()?,
3682        })
3683    }
3684}
3685
3686impl TryFrom<RewardPeriodLength> for updates::RewardPeriodLength {
3687    type Error = tonic::Status;
3688
3689    fn try_from(value: RewardPeriodLength) -> Result<Self, Self::Error> {
3690        Ok(Self::from(base::Epoch::from(value.value.require()?)))
3691    }
3692}
3693
3694impl From<Epoch> for base::Epoch {
3695    fn from(value: Epoch) -> Self {
3696        Self { epoch: value.value }
3697    }
3698}
3699
3700impl From<Round> for base::Round {
3701    fn from(value: Round) -> Self {
3702        Self { round: value.value }
3703    }
3704}
3705
3706impl TryFrom<PendingUpdate> for super::types::queries::PendingUpdate {
3707    type Error = tonic::Status;
3708
3709    fn try_from(message: PendingUpdate) -> Result<Self, Self::Error> {
3710        let effective_time = message.effective_time.require()?.into();
3711        let effect = message
3712            .effect
3713            .map(super::types::queries::PendingUpdateEffect::try_from)
3714            .transpose()?
3715            .into();
3716        Ok(Self {
3717            effective_time,
3718            effect,
3719        })
3720    }
3721}
3722
3723impl TryFrom<pending_update::Effect> for super::types::queries::PendingUpdateEffect {
3724    type Error = tonic::Status;
3725
3726    fn try_from(effect: pending_update::Effect) -> Result<Self, Self::Error> {
3727        use super::types::queries::PendingUpdateEffect;
3728        let out = match effect {
3729            pending_update::Effect::RootKeys(e) => PendingUpdateEffect::RootKeys(e.try_into()?),
3730            pending_update::Effect::Level1Keys(l1) => {
3731                PendingUpdateEffect::Level1Keys(l1.try_into()?)
3732            }
3733            pending_update::Effect::Level2KeysCpv0(l2) => {
3734                PendingUpdateEffect::Level2KeysCPV0(l2.try_into()?)
3735            }
3736            pending_update::Effect::Level2KeysCpv1(l2) => {
3737                PendingUpdateEffect::Level2KeysCPV1(l2.try_into()?)
3738            }
3739            pending_update::Effect::Protocol(p) => PendingUpdateEffect::Protocol(p.try_into()?),
3740            pending_update::Effect::ElectionDifficulty(ed) => {
3741                PendingUpdateEffect::ElectionDifficulty(ed.try_into()?)
3742            }
3743            pending_update::Effect::EuroPerEnergy(ee) => {
3744                PendingUpdateEffect::EuroPerEnergy(ee.try_into()?)
3745            }
3746            pending_update::Effect::MicroCcdPerEuro(mpe) => {
3747                PendingUpdateEffect::MicroCcdPerEnergy(mpe.try_into()?)
3748            }
3749            pending_update::Effect::FoundationAccount(fa) => {
3750                PendingUpdateEffect::FoundationAccount(fa.try_into()?)
3751            }
3752            pending_update::Effect::MintDistributionCpv0(md) => {
3753                PendingUpdateEffect::MintDistributionV0(md.try_into()?)
3754            }
3755            pending_update::Effect::MintDistributionCpv1(md) => {
3756                PendingUpdateEffect::MintDistributionV1(md.try_into()?)
3757            }
3758            pending_update::Effect::TransactionFeeDistribution(tfd) => {
3759                PendingUpdateEffect::TransactionFeeDistribution(tfd.try_into()?)
3760            }
3761            pending_update::Effect::GasRewards(gr) => {
3762                PendingUpdateEffect::GasRewards(gr.try_into()?)
3763            }
3764            pending_update::Effect::PoolParametersCpv0(pp) => {
3765                PendingUpdateEffect::PoolParametersV0(pp.try_into()?)
3766            }
3767            pending_update::Effect::PoolParametersCpv1(pp) => {
3768                PendingUpdateEffect::PoolParametersV1(pp.try_into()?)
3769            }
3770            pending_update::Effect::AddAnonymityRevoker(aar) => {
3771                PendingUpdateEffect::AddAnonymityRevoker(Box::new(aar.try_into()?))
3772            }
3773            pending_update::Effect::AddIdentityProvider(aidp) => {
3774                PendingUpdateEffect::AddIdentityProvider(Box::new(aidp.try_into()?))
3775            }
3776            pending_update::Effect::CooldownParameters(cdp) => {
3777                PendingUpdateEffect::CooldownParameters(cdp.try_into()?)
3778            }
3779            pending_update::Effect::TimeParameters(tp) => {
3780                PendingUpdateEffect::TimeParameters(tp.try_into()?)
3781            }
3782            pending_update::Effect::GasRewardsCpv2(update) => {
3783                PendingUpdateEffect::GasRewardsV1(update.try_into()?)
3784            }
3785            pending_update::Effect::TimeoutParameters(update) => {
3786                PendingUpdateEffect::TimeoutParameters(update.try_into()?)
3787            }
3788            pending_update::Effect::MinBlockTime(update) => {
3789                PendingUpdateEffect::MinBlockTime(update.into())
3790            }
3791            pending_update::Effect::BlockEnergyLimit(update) => {
3792                PendingUpdateEffect::BlockEnergyLimit(update.into())
3793            }
3794            pending_update::Effect::FinalizationCommitteeParameters(update) => {
3795                PendingUpdateEffect::FinalizationCommitteeParameters(update.try_into()?)
3796            }
3797            pending_update::Effect::ValidatorScoreParameters(update) => {
3798                PendingUpdateEffect::ValidatorScoreParameters(update.try_into()?)
3799            }
3800        };
3801        Ok(out)
3802    }
3803}
3804
3805impl From<SequenceNumber> for super::types::UpdateSequenceNumber {
3806    fn from(message: SequenceNumber) -> Self {
3807        message.value.into()
3808    }
3809}
3810
3811impl From<UpdateSequenceNumber> for super::types::UpdateSequenceNumber {
3812    fn from(message: UpdateSequenceNumber) -> Self {
3813        message.value.into()
3814    }
3815}
3816
3817impl TryFrom<NextUpdateSequenceNumbers> for super::types::queries::NextUpdateSequenceNumbers {
3818    type Error = tonic::Status;
3819
3820    fn try_from(message: NextUpdateSequenceNumbers) -> Result<Self, Self::Error> {
3821        Ok(Self {
3822            root_keys: message.root_keys.require()?.into(),
3823            level_1_keys: message.level1_keys.require()?.into(),
3824            level_2_keys: message.level2_keys.require()?.into(),
3825            protocol: message.protocol.require()?.into(),
3826            election_difficulty: message.election_difficulty.require()?.into(),
3827            euro_per_energy: message.euro_per_energy.require()?.into(),
3828            micro_ccd_per_euro: message.micro_ccd_per_euro.require()?.into(),
3829            foundation_account: message.foundation_account.require()?.into(),
3830            mint_distribution: message.mint_distribution.require()?.into(),
3831            transaction_fee_distribution: message.transaction_fee_distribution.require()?.into(),
3832            gas_rewards: message.gas_rewards.require()?.into(),
3833            pool_parameters: message.pool_parameters.require()?.into(),
3834            add_anonymity_revoker: message.add_anonymity_revoker.require()?.into(),
3835            add_identity_provider: message.add_identity_provider.require()?.into(),
3836            cooldown_parameters: message.cooldown_parameters.require()?.into(),
3837            time_parameters: message.time_parameters.require()?.into(),
3838            timeout_parameters: message.timeout_parameters.require()?.into(),
3839            min_block_time: message.min_block_time.require()?.into(),
3840            block_energy_limit: message.block_energy_limit.require()?.into(),
3841            finalization_committee_parameters: message
3842                .finalization_committee_parameters
3843                .require()?
3844                .into(),
3845            validator_score_parameters: message
3846                .validator_score_parameters
3847                .map(Into::into)
3848                .unwrap_or_default(),
3849            protocol_level_tokens: message
3850                .protocol_level_tokens
3851                .map(Into::into)
3852                .unwrap_or_default(),
3853        })
3854    }
3855}
3856
3857impl TryFrom<QuorumSignature> for super::types::block_certificates::QuorumSignature {
3858    type Error = tonic::Status;
3859
3860    fn try_from(message: QuorumSignature) -> Result<Self, Self::Error> {
3861        consume(&message.value)
3862    }
3863}
3864
3865impl TryFrom<QuorumCertificate> for super::types::block_certificates::QuorumCertificate {
3866    type Error = tonic::Status;
3867
3868    fn try_from(message: QuorumCertificate) -> Result<Self, Self::Error> {
3869        Ok(Self {
3870            block_hash: message.block_hash.require()?.try_into()?,
3871            round: message.round.require()?.into(),
3872            epoch: message.epoch.require()?.into(),
3873            aggregate_signature: message.aggregate_signature.require()?.try_into()?,
3874            signatories: message
3875                .signatories
3876                .into_iter()
3877                .map(From::from)
3878                .collect::<BTreeSet<super::types::BakerId>>(),
3879        })
3880    }
3881}
3882
3883impl TryFrom<SuccessorProof> for super::hashes::SuccessorProof {
3884    type Error = tonic::Status;
3885
3886    fn try_from(message: SuccessorProof) -> Result<Self, Self::Error> {
3887        match message.value.try_into() {
3888            Ok(hash) => Ok(Self::new(hash)),
3889            Err(_) => Err(tonic::Status::internal(
3890                "Unexpected successor proof format.",
3891            )),
3892        }
3893    }
3894}
3895
3896impl TryFrom<EpochFinalizationEntry> for super::types::block_certificates::EpochFinalizationEntry {
3897    type Error = tonic::Status;
3898
3899    fn try_from(message: EpochFinalizationEntry) -> Result<Self, Self::Error> {
3900        Ok(Self {
3901            finalized_qc: message.finalized_qc.require()?.try_into()?,
3902            successor_qc: message.successor_qc.require()?.try_into()?,
3903            successor_proof: message.successor_proof.require()?.try_into()?,
3904        })
3905    }
3906}
3907
3908impl TryFrom<FinalizerRound> for super::types::block_certificates::FinalizerRound {
3909    type Error = tonic::Status;
3910
3911    fn try_from(message: FinalizerRound) -> Result<Self, Self::Error> {
3912        Ok(Self {
3913            round: message.round.require()?.into(),
3914            finalizers: message
3915                .finalizers
3916                .into_iter()
3917                .map(From::from)
3918                .collect::<Vec<super::types::BakerId>>(),
3919        })
3920    }
3921}
3922
3923impl TryFrom<TimeoutSignature> for super::types::block_certificates::TimeoutSignature {
3924    type Error = tonic::Status;
3925
3926    fn try_from(message: TimeoutSignature) -> Result<Self, Self::Error> {
3927        consume(&message.value)
3928    }
3929}
3930
3931impl TryFrom<TimeoutCertificate> for super::types::block_certificates::TimeoutCertificate {
3932    type Error = tonic::Status;
3933
3934    fn try_from(message: TimeoutCertificate) -> Result<Self, Self::Error> {
3935        Ok(
3936            Self {
3937                round: message.round.require()?.into(),
3938                min_epoch: message.min_epoch.require()?.into(),
3939                qc_rounds_first_epoch:
3940                    message
3941                        .qc_rounds_first_epoch
3942                        .into_iter()
3943                        .map(TryFrom::try_from)
3944                        .collect::<Result<
3945                            Vec<super::types::block_certificates::FinalizerRound>,
3946                            tonic::Status,
3947                        >>()?,
3948                qc_rounds_second_epoch:
3949                    message
3950                        .qc_rounds_second_epoch
3951                        .into_iter()
3952                        .map(TryFrom::try_from)
3953                        .collect::<Result<
3954                            Vec<super::types::block_certificates::FinalizerRound>,
3955                            tonic::Status,
3956                        >>()?,
3957                aggregate_signature: message.aggregate_signature.require()?.try_into()?,
3958            },
3959        )
3960    }
3961}
3962
3963impl TryFrom<BlockCertificates> for super::types::block_certificates::BlockCertificates {
3964    type Error = tonic::Status;
3965
3966    fn try_from(message: BlockCertificates) -> Result<Self, Self::Error> {
3967        Ok(Self {
3968            quorum_certificate: message
3969                .quorum_certificate
3970                .map(TryFrom::try_from)
3971                .transpose()?,
3972            timeout_certificate: message
3973                .timeout_certificate
3974                .map(TryFrom::try_from)
3975                .transpose()?,
3976            epoch_finalization_entry: message
3977                .epoch_finalization_entry
3978                .map(TryFrom::try_from)
3979                .transpose()?,
3980        })
3981    }
3982}
3983
3984impl TryFrom<WinningBaker> for super::types::WinningBaker {
3985    type Error = tonic::Status;
3986
3987    fn try_from(wb: WinningBaker) -> Result<Self, Self::Error> {
3988        Ok(Self {
3989            round: wb.round.require()?.value.into(),
3990            winner: super::types::BakerId {
3991                id: wb.winner.require()?.value.into(),
3992            },
3993            present: wb.present,
3994        })
3995    }
3996}
3997
3998impl TryFrom<AccountPending> for super::types::AccountPending {
3999    type Error = tonic::Status;
4000
4001    fn try_from(pending: AccountPending) -> Result<Self, Self::Error> {
4002        Ok(Self {
4003            account_index: pending.account_index.require()?.into(),
4004            first_timestamp: pending.first_timestamp.require()?.into(),
4005        })
4006    }
4007}
4008
4009impl TryFrom<BakerRewardPeriodInfo> for super::types::BakerRewardPeriodInfo {
4010    type Error = tonic::Status;
4011
4012    fn try_from(message: BakerRewardPeriodInfo) -> Result<Self, Self::Error> {
4013        Ok(Self {
4014            baker: message.baker.require()?.try_into()?,
4015            effective_stake: message.effective_stake.require()?.into(),
4016            commission_rates: message.commission_rates.require()?.try_into()?,
4017            equity_capital: message.equity_capital.require()?.into(),
4018            delegated_capital: message.delegated_capital.require()?.into(),
4019            is_finalizer: message.is_finalizer,
4020        })
4021    }
4022}
4023
4024impl From<FinalizerIndex> for super::types::block_certificates::raw::FinalizerIndex {
4025    fn from(value: FinalizerIndex) -> Self {
4026        Self { index: value.value }
4027    }
4028}
4029
4030impl TryFrom<QuorumMessage> for super::types::block_certificates::raw::QuorumMessage {
4031    type Error = tonic::Status;
4032
4033    fn try_from(message: QuorumMessage) -> Result<Self, Self::Error> {
4034        Ok(Self {
4035            signature: message.signature.require()?.try_into()?,
4036            block: message.block.require()?.try_into()?,
4037            finalizer: message.finalizer.require()?.into(),
4038            round: message.round.require()?.into(),
4039            epoch: message.epoch.require()?.into(),
4040        })
4041    }
4042}
4043
4044impl TryFrom<RawQuorumCertificate> for super::types::block_certificates::raw::QuorumCertificate {
4045    type Error = tonic::Status;
4046
4047    fn try_from(value: RawQuorumCertificate) -> Result<Self, Self::Error> {
4048        Ok(Self {
4049            block_hash: value.block_hash.require()?.try_into()?,
4050            round: value.round.require()?.into(),
4051            epoch: value.epoch.require()?.into(),
4052            aggregate_signature: value.aggregate_signature.require()?.try_into()?,
4053            signatories: value.signatories.into_iter().map(From::from).collect(),
4054        })
4055    }
4056}
4057
4058impl TryFrom<RawTimeoutCertificate> for super::types::block_certificates::raw::TimeoutCertificate {
4059    type Error = tonic::Status;
4060
4061    fn try_from(value: RawTimeoutCertificate) -> Result<Self, Self::Error> {
4062        Ok(Self {
4063            round: value.round.require()?.into(),
4064            min_epoch: value.min_epoch.require()?.into(),
4065            qc_rounds_first_epoch: value
4066                .qc_rounds_first_epoch
4067                .into_iter()
4068                .map(TryFrom::try_from)
4069                .collect::<Result<_, _>>()?,
4070            qc_rounds_second_epoch: value
4071                .qc_rounds_second_epoch
4072                .into_iter()
4073                .map(TryFrom::try_from)
4074                .collect::<Result<_, _>>()?,
4075            aggregate_signature: value.aggregate_signature.require()?.try_into()?,
4076        })
4077    }
4078}
4079
4080impl TryFrom<RawFinalizerRound> for super::types::block_certificates::raw::FinalizerRound {
4081    type Error = tonic::Status;
4082
4083    fn try_from(value: RawFinalizerRound) -> Result<Self, Self::Error> {
4084        Ok(Self {
4085            round: value.round.require()?.into(),
4086            finalizers: value.finalizers.into_iter().map(From::from).collect(),
4087        })
4088    }
4089}
4090
4091impl TryFrom<BlockSignature> for super::types::block_certificates::raw::BlockSignature {
4092    type Error = tonic::Status;
4093
4094    fn try_from(message: BlockSignature) -> Result<Self, Self::Error> {
4095        consume(&message.value)
4096    }
4097}
4098
4099impl TryFrom<TimeoutMessage> for super::types::block_certificates::raw::TimeoutMessage {
4100    type Error = tonic::Status;
4101
4102    fn try_from(value: TimeoutMessage) -> Result<Self, Self::Error> {
4103        Ok(Self {
4104            finalizer: value.finalizer.require()?.into(),
4105            round: value.round.require()?.into(),
4106            epoch: value.epoch.require()?.into(),
4107            quorum_certificate: value.quorum_certificate.require()?.try_into()?,
4108            signature: value.signature.require()?.try_into()?,
4109            message_signature: value.message_signature.require()?.try_into()?,
4110        })
4111    }
4112}
4113
4114impl TryFrom<RawFinalizationEntry> for super::types::block_certificates::raw::FinalizationEntry {
4115    type Error = tonic::Status;
4116
4117    fn try_from(value: RawFinalizationEntry) -> Result<Self, Self::Error> {
4118        Ok(Self {
4119            finalized_qc: value.finalized_qc.require()?.try_into()?,
4120            successor_qc: value.successor_qc.require()?.try_into()?,
4121            successor_proof: value.successor_proof.require()?.try_into()?,
4122        })
4123    }
4124}
4125
4126impl TryFrom<TimeoutMessages> for super::types::block_certificates::raw::TimeoutMessages {
4127    type Error = tonic::Status;
4128
4129    fn try_from(value: TimeoutMessages) -> Result<Self, Self::Error> {
4130        Ok(Self {
4131            first_epoch: value.first_epoch.require()?.into(),
4132            first_epoch_timeouts: value
4133                .first_epoch_timeouts
4134                .into_iter()
4135                .map(TryFrom::try_from)
4136                .collect::<Result<_, _>>()?,
4137            second_epoch_timeouts: value
4138                .second_epoch_timeouts
4139                .into_iter()
4140                .map(TryFrom::try_from)
4141                .collect::<Result<_, _>>()?,
4142        })
4143    }
4144}
4145
4146impl TryFrom<PersistentRoundStatus> for super::types::queries::PersistentRoundStatus {
4147    type Error = tonic::Status;
4148
4149    fn try_from(value: PersistentRoundStatus) -> Result<Self, Self::Error> {
4150        Ok(Self {
4151            last_signed_quorum_message: value
4152                .last_signed_quorum_message
4153                .map(TryFrom::try_from)
4154                .transpose()?,
4155            last_signed_timeout_message: value
4156                .last_signed_timeout_message
4157                .map(TryFrom::try_from)
4158                .transpose()?,
4159            last_baked_round: value.last_baked_round.require()?.into(),
4160            latest_timeout: value.latest_timeout.map(TryFrom::try_from).transpose()?,
4161        })
4162    }
4163}
4164
4165impl TryFrom<RoundTimeout> for super::types::queries::RoundTimeout {
4166    type Error = tonic::Status;
4167
4168    fn try_from(value: RoundTimeout) -> Result<Self, Self::Error> {
4169        Ok(Self {
4170            timeout_certificate: value.timeout_certificate.require()?.try_into()?,
4171            quorum_certificate: value.quorum_certificate.require()?.try_into()?,
4172        })
4173    }
4174}
4175
4176impl TryFrom<RoundStatus> for super::types::queries::RoundStatus {
4177    type Error = tonic::Status;
4178
4179    fn try_from(value: RoundStatus) -> Result<Self, Self::Error> {
4180        Ok(Self {
4181            current_round: value.current_round.require()?.into(),
4182            highest_certified_block: value.highest_certified_block.require()?.try_into()?,
4183            previous_round_timeout: value
4184                .previous_round_timeout
4185                .map(TryFrom::try_from)
4186                .transpose()?,
4187            round_eligible_to_bake: value.round_eligible_to_bake,
4188            current_epoch: value.current_epoch.require()?.into(),
4189            last_epoch_finalization_entry: value
4190                .last_epoch_finalization_entry
4191                .map(TryFrom::try_from)
4192                .transpose()?,
4193            current_timeout: value.current_timeout.require()?.into(),
4194        })
4195    }
4196}
4197
4198impl TryFrom<BlockTableSummary> for super::types::queries::BlockTableSummary {
4199    type Error = tonic::Status;
4200
4201    fn try_from(value: BlockTableSummary) -> Result<Self, Self::Error> {
4202        Ok(Self {
4203            dead_block_cache_size: value.dead_block_cache_size,
4204            live_blocks: value
4205                .live_blocks
4206                .into_iter()
4207                .map(TryFrom::try_from)
4208                .collect::<Result<_, _>>()?,
4209        })
4210    }
4211}
4212
4213impl TryFrom<RoundExistingBlock> for super::types::queries::RoundExistingBlock {
4214    type Error = tonic::Status;
4215
4216    fn try_from(value: RoundExistingBlock) -> Result<Self, Self::Error> {
4217        Ok(Self {
4218            round: value.round.require()?.into(),
4219            baker: value.baker.require()?.into(),
4220            block: value.block.require()?.try_into()?,
4221        })
4222    }
4223}
4224
4225impl TryFrom<RoundExistingQc> for super::types::queries::RoundExistingQC {
4226    type Error = tonic::Status;
4227
4228    fn try_from(value: RoundExistingQc) -> Result<Self, Self::Error> {
4229        Ok(Self {
4230            round: value.round.require()?.into(),
4231            epoch: value.epoch.require()?.into(),
4232        })
4233    }
4234}
4235
4236impl TryFrom<FullBakerInfo> for super::types::queries::FullBakerInfo {
4237    type Error = tonic::Status;
4238
4239    fn try_from(value: FullBakerInfo) -> Result<Self, Self::Error> {
4240        Ok(Self {
4241            baker_identity: value.baker_identity.require()?.into(),
4242            election_verify_key: value.election_verify_key.require()?.try_into()?,
4243            signature_verify_key: value.signature_verify_key.require()?.try_into()?,
4244            aggregation_verify_key: value.aggregation_verify_key.require()?.try_into()?,
4245            stake: value.stake.require()?.into(),
4246        })
4247    }
4248}
4249
4250impl TryFrom<FinalizationCommitteeHash> for concordium_base::hashes::FinalizationCommitteeHash {
4251    type Error = tonic::Status;
4252
4253    fn try_from(value: FinalizationCommitteeHash) -> Result<Self, Self::Error> {
4254        match value.value.try_into() {
4255            Ok(hash) => Ok(Self::new(hash)),
4256            Err(_) => Err(tonic::Status::internal(
4257                "Unexpected finalization committee hash format.",
4258            )),
4259        }
4260    }
4261}
4262
4263impl TryFrom<BakersAndFinalizers> for super::types::queries::BakersAndFinalizers {
4264    type Error = tonic::Status;
4265
4266    fn try_from(value: BakersAndFinalizers) -> Result<Self, Self::Error> {
4267        Ok(Self {
4268            bakers: value
4269                .bakers
4270                .into_iter()
4271                .map(TryFrom::try_from)
4272                .collect::<Result<_, _>>()?,
4273            finalizers: value.finalizers.into_iter().map(From::from).collect(),
4274            baker_total_stake: value.baker_total_stake.require()?.into(),
4275            finalizer_total_stake: value.finalizer_total_stake.require()?.into(),
4276            finalization_committee_hash: value.finalization_committee_hash.require()?.try_into()?,
4277        })
4278    }
4279}
4280
4281impl TryFrom<EpochBakers> for super::types::queries::EpochBakers {
4282    type Error = tonic::Status;
4283
4284    fn try_from(value: EpochBakers) -> Result<Self, Self::Error> {
4285        Ok(Self {
4286            previous_epoch_bakers: value.previous_epoch_bakers.require()?.try_into()?,
4287            current_epoch_bakers: value
4288                .current_epoch_bakers
4289                .map(TryFrom::try_from)
4290                .transpose()?,
4291            next_epoch_bakers: value.next_epoch_bakers.map(TryFrom::try_from).transpose()?,
4292            next_payday: value.next_payday.require()?.into(),
4293        })
4294    }
4295}
4296
4297impl TryFrom<BranchBlocks> for Vec<super::BlockHash> {
4298    type Error = tonic::Status;
4299
4300    fn try_from(value: BranchBlocks) -> Result<Self, Self::Error> {
4301        value
4302            .blocks_at_branch_height
4303            .into_iter()
4304            .map(TryFrom::try_from)
4305            .collect()
4306    }
4307}
4308
4309impl TryFrom<ConsensusDetailedStatus> for super::types::queries::ConsensusDetailedStatus {
4310    type Error = tonic::Status;
4311
4312    fn try_from(value: ConsensusDetailedStatus) -> Result<Self, Self::Error> {
4313        Ok(Self {
4314            genesis_block: value.genesis_block.require()?.try_into()?,
4315            persistent_round_status: value.persistent_round_status.require()?.try_into()?,
4316            round_status: value.round_status.require()?.try_into()?,
4317            non_finalized_transaction_count: value.non_finalized_transaction_count,
4318            transaction_table_purge_counter: value.transaction_table_purge_counter,
4319            block_table: value.block_table.require()?.try_into()?,
4320            branches: value
4321                .branches
4322                .into_iter()
4323                .map(TryFrom::try_from)
4324                .collect::<Result<_, _>>()?,
4325            round_existing_blocks: value
4326                .round_existing_blocks
4327                .into_iter()
4328                .map(TryFrom::try_from)
4329                .collect::<Result<_, _>>()?,
4330            round_existing_qcs: value
4331                .round_existing_qcs
4332                .into_iter()
4333                .map(TryFrom::try_from)
4334                .collect::<Result<_, _>>()?,
4335            genesis_block_height: value.genesis_block_height.require()?.into(),
4336            last_finalized_block: value.last_finalized_block.require()?.try_into()?,
4337            last_finalized_block_height: value.last_finalized_block_height.require()?.into(),
4338            latest_finalization_entry: value
4339                .latest_finalization_entry
4340                .map(TryFrom::try_from)
4341                .transpose()?,
4342            epoch_bakers: value.epoch_bakers.require()?.try_into()?,
4343            timeout_messages: value.timeout_messages.map(TryFrom::try_from).transpose()?,
4344            terminal_block: value.terminal_block.map(TryFrom::try_from).transpose()?,
4345        })
4346    }
4347}
4348
4349#[cfg(test)]
4350mod test {
4351    use concordium_base::{
4352        base::{self, PartsPerHundredThousands, UpdateKeyPair},
4353        common::{Deserial, Serial},
4354        contracts_common,
4355    };
4356    use rand::{rngs::StdRng, SeedableRng};
4357
4358    use super::*;
4359
4360    #[test]
4361    fn test_try_from_branch() {
4362        use crate::types::queries::Branch as QBranch;
4363
4364        let from = Branch {
4365            block_hash: Some(BlockHash {
4366                value: vec![0u8; 32],
4367            }),
4368            children: vec![
4369                Branch {
4370                    block_hash: Some(BlockHash {
4371                        value: vec![1u8; 32],
4372                    }),
4373                    children: vec![],
4374                },
4375                Branch {
4376                    block_hash: Some(BlockHash {
4377                        value: vec![2u8; 32],
4378                    }),
4379                    children: vec![Branch {
4380                        block_hash: Some(BlockHash {
4381                            value: vec![3u8; 32],
4382                        }),
4383                        children: vec![],
4384                    }],
4385                },
4386            ],
4387        };
4388
4389        let to_target = QBranch {
4390            block_hash: [0u8; 32].into(),
4391            children: vec![
4392                QBranch {
4393                    block_hash: [2u8; 32].into(),
4394                    children: vec![QBranch {
4395                        block_hash: [3u8; 32].into(),
4396                        children: vec![],
4397                    }],
4398                },
4399                QBranch {
4400                    block_hash: [1u8; 32].into(),
4401                    children: vec![],
4402                },
4403            ],
4404        };
4405        let to = QBranch::try_from(from).expect("Failed to convert branch");
4406
4407        assert_eq!(to, to_target);
4408    }
4409
4410    /// Generate an `UpdatePublicKey` and its serialized representation.
4411    fn gen_public_key(rng: &mut StdRng) -> (base::UpdatePublicKey, Vec<u8>) {
4412        let key = base::UpdatePublicKey::from(&UpdateKeyPair::generate(rng));
4413        let mut buffer = Vec::with_capacity(33);
4414        key.serial(&mut buffer);
4415        // Drop the first byte which indicates the key is Ed25519.
4416        let bytes = buffer[1..].to_vec();
4417        // Deserialize the serialized representation so that the key is
4418        // represented normalized (i.e. with the Z coordinate being 1 in the
4419        // projective representation).
4420        let norm_key = base::UpdatePublicKey::deserial(&mut &buffer[..]).unwrap();
4421        (norm_key, bytes)
4422    }
4423
4424    #[test]
4425    fn test_try_from_chain_parameters_v0() {
4426        let mut rng = StdRng::seed_from_u64(0);
4427        let (root_key, root_key_bytes) = gen_public_key(&mut rng);
4428        let (level_1_key, level_1_key_bytes) = gen_public_key(&mut rng);
4429        let (level_2_key_1, level_2_key_1_bytes) = gen_public_key(&mut rng);
4430        let (level_2_key_2, level_2_key_2_bytes) = gen_public_key(&mut rng);
4431        let cpv0 = ChainParametersV0 {
4432            election_difficulty: Some(ElectionDifficulty {
4433                value: Some(AmountFraction {
4434                    parts_per_hundred_thousand: 11111,
4435                }),
4436            }),
4437            euro_per_energy: Some(ExchangeRate {
4438                value: Some(Ratio {
4439                    numerator: 13,
4440                    denominator: 17,
4441                }),
4442            }),
4443            micro_ccd_per_euro: Some(ExchangeRate {
4444                value: Some(Ratio {
4445                    numerator: 19,
4446                    denominator: 23,
4447                }),
4448            }),
4449            baker_cooldown_epochs: Some(Epoch { value: 29 }),
4450            account_creation_limit: Some(CredentialsPerBlockLimit { value: 31 }),
4451            mint_distribution: Some(MintDistributionCpv0 {
4452                mint_per_slot: Some(MintRate {
4453                    mantissa: 37,
4454                    exponent: 41,
4455                }),
4456                baking_reward: Some(AmountFraction {
4457                    parts_per_hundred_thousand: 43,
4458                }),
4459                finalization_reward: Some(AmountFraction {
4460                    parts_per_hundred_thousand: 47,
4461                }),
4462            }),
4463            transaction_fee_distribution: Some(TransactionFeeDistribution {
4464                baker: Some(AmountFraction {
4465                    parts_per_hundred_thousand: 53,
4466                }),
4467                gas_account: Some(AmountFraction {
4468                    parts_per_hundred_thousand: 59,
4469                }),
4470            }),
4471            gas_rewards: Some(GasRewards {
4472                baker: Some(AmountFraction {
4473                    parts_per_hundred_thousand: 61,
4474                }),
4475                finalization_proof: Some(AmountFraction {
4476                    parts_per_hundred_thousand: 67,
4477                }),
4478                account_creation: Some(AmountFraction {
4479                    parts_per_hundred_thousand: 71,
4480                }),
4481                chain_update: Some(AmountFraction {
4482                    parts_per_hundred_thousand: 73,
4483                }),
4484            }),
4485            foundation_account: Some(AccountAddress {
4486                value: vec![79u8; 32],
4487            }),
4488            minimum_threshold_for_baking: Some(Amount { value: 83 }),
4489            root_keys: Some(HigherLevelKeys {
4490                keys: vec![UpdatePublicKey {
4491                    value: root_key_bytes,
4492                }],
4493                threshold: Some(UpdateKeysThreshold { value: 97 }),
4494            }),
4495            level1_keys: Some(HigherLevelKeys {
4496                keys: vec![UpdatePublicKey {
4497                    value: level_1_key_bytes,
4498                }],
4499                threshold: Some(UpdateKeysThreshold { value: 103 }),
4500            }),
4501            level2_keys: Some(AuthorizationsV0 {
4502                keys: vec![
4503                    UpdatePublicKey {
4504                        value: level_2_key_1_bytes,
4505                    },
4506                    UpdatePublicKey {
4507                        value: level_2_key_2_bytes,
4508                    },
4509                ],
4510                emergency: Some(AccessStructure {
4511                    access_public_keys: vec![UpdateKeysIndex { value: 113 }],
4512                    access_threshold: Some(UpdateKeysThreshold { value: 127 }),
4513                }),
4514                protocol: Some(AccessStructure {
4515                    access_public_keys: vec![UpdateKeysIndex { value: 131 }],
4516                    access_threshold: Some(UpdateKeysThreshold { value: 137 }),
4517                }),
4518                parameter_consensus: Some(AccessStructure {
4519                    access_public_keys: vec![UpdateKeysIndex { value: 139 }],
4520                    access_threshold: Some(UpdateKeysThreshold { value: 149 }),
4521                }),
4522                parameter_euro_per_energy: Some(AccessStructure {
4523                    access_public_keys: vec![UpdateKeysIndex { value: 151 }],
4524                    access_threshold: Some(UpdateKeysThreshold { value: 157 }),
4525                }),
4526                parameter_micro_ccd_per_euro: Some(AccessStructure {
4527                    access_public_keys: vec![UpdateKeysIndex { value: 173 }],
4528                    access_threshold: Some(UpdateKeysThreshold { value: 179 }),
4529                }),
4530                parameter_foundation_account: Some(AccessStructure {
4531                    access_public_keys: vec![UpdateKeysIndex { value: 181 }],
4532                    access_threshold: Some(UpdateKeysThreshold { value: 191 }),
4533                }),
4534                parameter_mint_distribution: Some(AccessStructure {
4535                    access_public_keys: vec![UpdateKeysIndex { value: 193 }],
4536                    access_threshold: Some(UpdateKeysThreshold { value: 197 }),
4537                }),
4538                parameter_transaction_fee_distribution: Some(AccessStructure {
4539                    access_public_keys: vec![UpdateKeysIndex { value: 199 }],
4540                    access_threshold: Some(UpdateKeysThreshold { value: 211 }),
4541                }),
4542                parameter_gas_rewards: Some(AccessStructure {
4543                    access_public_keys: vec![UpdateKeysIndex { value: 223 }],
4544                    access_threshold: Some(UpdateKeysThreshold { value: 227 }),
4545                }),
4546                pool_parameters: Some(AccessStructure {
4547                    access_public_keys: vec![UpdateKeysIndex { value: 229 }],
4548                    access_threshold: Some(UpdateKeysThreshold { value: 233 }),
4549                }),
4550                add_anonymity_revoker: Some(AccessStructure {
4551                    access_public_keys: vec![UpdateKeysIndex { value: 239 }],
4552                    access_threshold: Some(UpdateKeysThreshold { value: 241 }),
4553                }),
4554                add_identity_provider: Some(AccessStructure {
4555                    access_public_keys: vec![UpdateKeysIndex { value: 251 }],
4556                    access_threshold: Some(UpdateKeysThreshold { value: 257 }),
4557                }),
4558            }),
4559        };
4560        let params = ChainParameters {
4561            parameters: Some(generated::chain_parameters::Parameters::V0(cpv0)),
4562        };
4563        let converted = crate::v2::ChainParameters::try_from(params)
4564            .expect("Failed to convert chain parameters v0");
4565        let expected = crate::v2::ChainParameters {
4566            timeout_parameters: Default::default(),
4567            election_difficulty: Some(base::ElectionDifficulty::new_unchecked(11111)),
4568            min_block_time: None,
4569            block_energy_limit: None,
4570            euro_per_energy: Some(base::ExchangeRate::new_unchecked(13, 17)),
4571            micro_ccd_per_euro: Some(base::ExchangeRate::new_unchecked(19, 23)),
4572            cooldown_parameters: chain_parameters::CooldownParameters {
4573                baker_cooldown_epochs: Some(base::Epoch::from(29)),
4574                pool_owner_cooldown: None,
4575                delegator_cooldown: None,
4576            },
4577            reward_period_length: None,
4578            mint_per_payday: None,
4579            mint_per_slot: Some(base::MintRate {
4580                mantissa: 37,
4581                exponent: 41,
4582            }),
4583            account_creation_limit: Some(base::CredentialsPerBlockLimit::from(31)),
4584            mint_distribution: chain_parameters::MintDistribution {
4585                baking_reward: Some(base::AmountFraction::new_unchecked(43)),
4586                finalization_reward: Some(base::AmountFraction::new_unchecked(47)),
4587            },
4588            transaction_fee_distribution: chain_parameters::TransactionFeeDistribution {
4589                baker: Some(base::AmountFraction::new_unchecked(53)),
4590                gas_account: Some(base::AmountFraction::new_unchecked(59)),
4591            },
4592            gas_rewards: chain_parameters::GasRewards {
4593                baker: Some(base::AmountFraction::new_unchecked(61)),
4594                finalization_proof: Some(base::AmountFraction::new_unchecked(67)),
4595                account_creation: Some(base::AmountFraction::new_unchecked(71)),
4596                chain_update: Some(base::AmountFraction::new_unchecked(73)),
4597            },
4598            foundation_account: Some(contracts_common::AccountAddress([79u8; 32])),
4599            staking_parameters: chain_parameters::StakingParameters {
4600                minimum_equity_capital: Some(contracts_common::Amount::from_micro_ccd(83)),
4601                ..Default::default()
4602            },
4603            finalization_committee_parameters: Default::default(),
4604            validator_max_missed_rounds: None,
4605            keys: chain_parameters::UpdateKeys {
4606                root_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
4607                    concordium_base::updates::RootKeysKind,
4608                > {
4609                    keys: vec![base::UpdatePublicKey::from(
4610                        crate::id::types::VerifyKey::from(root_key),
4611                    )],
4612                    threshold: 97.try_into().unwrap(),
4613                    _phantom: Default::default(),
4614                }),
4615                level_1_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
4616                    concordium_base::updates::Level1KeysKind,
4617                > {
4618                    keys: vec![base::UpdatePublicKey::from(
4619                        crate::id::types::VerifyKey::from(level_1_key),
4620                    )],
4621                    threshold: 103.try_into().unwrap(),
4622                    _phantom: Default::default(),
4623                }),
4624                level_2_keys: Some(chain_parameters::Level2Keys {
4625                    keys: vec![
4626                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
4627                            level_2_key_1,
4628                        )),
4629                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
4630                            level_2_key_2,
4631                        )),
4632                    ],
4633                    emergency: Some(updates::AccessStructure {
4634                        authorized_keys: [base::UpdateKeysIndex::from(113)].into(),
4635                        threshold: 127.try_into().unwrap(),
4636                    }),
4637                    protocol: Some(updates::AccessStructure {
4638                        authorized_keys: [base::UpdateKeysIndex::from(131)].into(),
4639                        threshold: 137.try_into().unwrap(),
4640                    }),
4641                    consensus: Some(updates::AccessStructure {
4642                        authorized_keys: [base::UpdateKeysIndex::from(139)].into(),
4643                        threshold: 149.try_into().unwrap(),
4644                    }),
4645                    euro_per_energy: Some(updates::AccessStructure {
4646                        authorized_keys: [base::UpdateKeysIndex::from(151)].into(),
4647                        threshold: 157.try_into().unwrap(),
4648                    }),
4649                    micro_ccd_per_euro: Some(updates::AccessStructure {
4650                        authorized_keys: [base::UpdateKeysIndex::from(173)].into(),
4651                        threshold: 179.try_into().unwrap(),
4652                    }),
4653                    foundation_account: Some(updates::AccessStructure {
4654                        authorized_keys: [base::UpdateKeysIndex::from(181)].into(),
4655                        threshold: 191.try_into().unwrap(),
4656                    }),
4657                    mint_distribution: Some(updates::AccessStructure {
4658                        authorized_keys: [base::UpdateKeysIndex::from(193)].into(),
4659                        threshold: 197.try_into().unwrap(),
4660                    }),
4661                    transaction_fee_distribution: Some(updates::AccessStructure {
4662                        authorized_keys: [base::UpdateKeysIndex::from(199)].into(),
4663                        threshold: 211.try_into().unwrap(),
4664                    }),
4665                    param_gas_rewards: Some(updates::AccessStructure {
4666                        authorized_keys: [base::UpdateKeysIndex::from(223)].into(),
4667                        threshold: 227.try_into().unwrap(),
4668                    }),
4669                    pool_parameters: Some(updates::AccessStructure {
4670                        authorized_keys: [base::UpdateKeysIndex::from(229)].into(),
4671                        threshold: 233.try_into().unwrap(),
4672                    }),
4673                    add_anonymity_revoker: Some(updates::AccessStructure {
4674                        authorized_keys: [base::UpdateKeysIndex::from(239)].into(),
4675                        threshold: 241.try_into().unwrap(),
4676                    }),
4677                    add_identity_provider: Some(updates::AccessStructure {
4678                        authorized_keys: [base::UpdateKeysIndex::from(251)].into(),
4679                        threshold: 257.try_into().unwrap(),
4680                    }),
4681                    cooldown_parameters: None,
4682                    time_parameters: None,
4683                    create_plt: None,
4684                }),
4685            },
4686        };
4687        assert_eq!(converted, expected);
4688    }
4689
4690    #[test]
4691    fn test_try_from_chain_parameters_v1() {
4692        let mut rng = StdRng::seed_from_u64(1);
4693        let (root_key, root_key_bytes) = gen_public_key(&mut rng);
4694        let (level_1_key, level_1_key_bytes) = gen_public_key(&mut rng);
4695        let (level_2_key_1, level_2_key_1_bytes) = gen_public_key(&mut rng);
4696        let (level_2_key_2, level_2_key_2_bytes) = gen_public_key(&mut rng);
4697        let cpv1 = ChainParametersV1 {
4698            election_difficulty: Some(ElectionDifficulty {
4699                value: Some(AmountFraction {
4700                    parts_per_hundred_thousand: 21111,
4701                }),
4702            }),
4703            euro_per_energy: Some(ExchangeRate {
4704                value: Some(Ratio {
4705                    numerator: 2,
4706                    denominator: 3,
4707                }),
4708            }),
4709            micro_ccd_per_euro: Some(ExchangeRate {
4710                value: Some(Ratio {
4711                    numerator: 4,
4712                    denominator: 5,
4713                }),
4714            }),
4715            cooldown_parameters: Some(CooldownParametersCpv1 {
4716                pool_owner_cooldown: Some(DurationSeconds { value: 6 }),
4717                delegator_cooldown: Some(DurationSeconds { value: 7 }),
4718            }),
4719            time_parameters: Some(TimeParametersCpv1 {
4720                reward_period_length: Some(RewardPeriodLength {
4721                    value: Some(Epoch { value: 8 }),
4722                }),
4723                mint_per_payday: Some(MintRate {
4724                    mantissa: 9,
4725                    exponent: 10,
4726                }),
4727            }),
4728            account_creation_limit: Some(CredentialsPerBlockLimit { value: 11 }),
4729            mint_distribution: Some(MintDistributionCpv1 {
4730                baking_reward: Some(AmountFraction {
4731                    parts_per_hundred_thousand: 12,
4732                }),
4733                finalization_reward: Some(AmountFraction {
4734                    parts_per_hundred_thousand: 13,
4735                }),
4736            }),
4737            transaction_fee_distribution: Some(TransactionFeeDistribution {
4738                baker: Some(AmountFraction {
4739                    parts_per_hundred_thousand: 14,
4740                }),
4741                gas_account: Some(AmountFraction {
4742                    parts_per_hundred_thousand: 15,
4743                }),
4744            }),
4745            gas_rewards: Some(GasRewards {
4746                baker: Some(AmountFraction {
4747                    parts_per_hundred_thousand: 16,
4748                }),
4749                finalization_proof: Some(AmountFraction {
4750                    parts_per_hundred_thousand: 17,
4751                }),
4752                account_creation: Some(AmountFraction {
4753                    parts_per_hundred_thousand: 18,
4754                }),
4755                chain_update: Some(AmountFraction {
4756                    parts_per_hundred_thousand: 19,
4757                }),
4758            }),
4759            foundation_account: Some(AccountAddress {
4760                value: vec![20u8; 32],
4761            }),
4762            pool_parameters: Some(PoolParametersCpv1 {
4763                passive_finalization_commission: Some(AmountFraction {
4764                    parts_per_hundred_thousand: 21,
4765                }),
4766                passive_baking_commission: Some(AmountFraction {
4767                    parts_per_hundred_thousand: 22,
4768                }),
4769                passive_transaction_commission: Some(AmountFraction {
4770                    parts_per_hundred_thousand: 23,
4771                }),
4772                commission_bounds: Some(CommissionRanges {
4773                    finalization: Some(InclusiveRangeAmountFraction {
4774                        min: Some(AmountFraction {
4775                            parts_per_hundred_thousand: 24,
4776                        }),
4777                        max: Some(AmountFraction {
4778                            parts_per_hundred_thousand: 25,
4779                        }),
4780                    }),
4781                    baking: Some(InclusiveRangeAmountFraction {
4782                        min: Some(AmountFraction {
4783                            parts_per_hundred_thousand: 26,
4784                        }),
4785                        max: Some(AmountFraction {
4786                            parts_per_hundred_thousand: 27,
4787                        }),
4788                    }),
4789                    transaction: Some(InclusiveRangeAmountFraction {
4790                        min: Some(AmountFraction {
4791                            parts_per_hundred_thousand: 28,
4792                        }),
4793                        max: Some(AmountFraction {
4794                            parts_per_hundred_thousand: 29,
4795                        }),
4796                    }),
4797                }),
4798                minimum_equity_capital: Some(Amount { value: 30 }),
4799                capital_bound: Some(CapitalBound {
4800                    value: Some(AmountFraction {
4801                        parts_per_hundred_thousand: 31,
4802                    }),
4803                }),
4804                leverage_bound: Some(LeverageFactor {
4805                    value: Some(Ratio {
4806                        numerator: 33,
4807                        denominator: 32,
4808                    }),
4809                }),
4810            }),
4811            root_keys: Some(HigherLevelKeys {
4812                keys: vec![UpdatePublicKey {
4813                    value: root_key_bytes,
4814                }],
4815                threshold: Some(UpdateKeysThreshold { value: 34 }),
4816            }),
4817            level1_keys: Some(HigherLevelKeys {
4818                keys: vec![UpdatePublicKey {
4819                    value: level_1_key_bytes,
4820                }],
4821                threshold: Some(UpdateKeysThreshold { value: 35 }),
4822            }),
4823            level2_keys: Some(AuthorizationsV1 {
4824                v0: Some(AuthorizationsV0 {
4825                    keys: vec![
4826                        UpdatePublicKey {
4827                            value: level_2_key_1_bytes,
4828                        },
4829                        UpdatePublicKey {
4830                            value: level_2_key_2_bytes,
4831                        },
4832                    ],
4833                    emergency: Some(AccessStructure {
4834                        access_public_keys: vec![UpdateKeysIndex { value: 113 }],
4835                        access_threshold: Some(UpdateKeysThreshold { value: 127 }),
4836                    }),
4837                    protocol: Some(AccessStructure {
4838                        access_public_keys: vec![UpdateKeysIndex { value: 131 }],
4839                        access_threshold: Some(UpdateKeysThreshold { value: 137 }),
4840                    }),
4841                    parameter_consensus: Some(AccessStructure {
4842                        access_public_keys: vec![UpdateKeysIndex { value: 139 }],
4843                        access_threshold: Some(UpdateKeysThreshold { value: 149 }),
4844                    }),
4845                    parameter_euro_per_energy: Some(AccessStructure {
4846                        access_public_keys: vec![UpdateKeysIndex { value: 151 }],
4847                        access_threshold: Some(UpdateKeysThreshold { value: 157 }),
4848                    }),
4849                    parameter_micro_ccd_per_euro: Some(AccessStructure {
4850                        access_public_keys: vec![UpdateKeysIndex { value: 173 }],
4851                        access_threshold: Some(UpdateKeysThreshold { value: 179 }),
4852                    }),
4853                    parameter_foundation_account: Some(AccessStructure {
4854                        access_public_keys: vec![UpdateKeysIndex { value: 181 }],
4855                        access_threshold: Some(UpdateKeysThreshold { value: 191 }),
4856                    }),
4857                    parameter_mint_distribution: Some(AccessStructure {
4858                        access_public_keys: vec![UpdateKeysIndex { value: 193 }],
4859                        access_threshold: Some(UpdateKeysThreshold { value: 197 }),
4860                    }),
4861                    parameter_transaction_fee_distribution: Some(AccessStructure {
4862                        access_public_keys: vec![UpdateKeysIndex { value: 199 }],
4863                        access_threshold: Some(UpdateKeysThreshold { value: 211 }),
4864                    }),
4865                    parameter_gas_rewards: Some(AccessStructure {
4866                        access_public_keys: vec![UpdateKeysIndex { value: 223 }],
4867                        access_threshold: Some(UpdateKeysThreshold { value: 227 }),
4868                    }),
4869                    pool_parameters: Some(AccessStructure {
4870                        access_public_keys: vec![UpdateKeysIndex { value: 229 }],
4871                        access_threshold: Some(UpdateKeysThreshold { value: 233 }),
4872                    }),
4873                    add_anonymity_revoker: Some(AccessStructure {
4874                        access_public_keys: vec![UpdateKeysIndex { value: 239 }],
4875                        access_threshold: Some(UpdateKeysThreshold { value: 241 }),
4876                    }),
4877                    add_identity_provider: Some(AccessStructure {
4878                        access_public_keys: vec![UpdateKeysIndex { value: 251 }],
4879                        access_threshold: Some(UpdateKeysThreshold { value: 257 }),
4880                    }),
4881                }),
4882                parameter_cooldown: Some(AccessStructure {
4883                    access_public_keys: vec![UpdateKeysIndex { value: 263 }],
4884                    access_threshold: Some(UpdateKeysThreshold { value: 269 }),
4885                }),
4886                parameter_time: Some(AccessStructure {
4887                    access_public_keys: vec![UpdateKeysIndex { value: 271 }],
4888                    access_threshold: Some(UpdateKeysThreshold { value: 277 }),
4889                }),
4890                create_plt: None,
4891            }),
4892        };
4893        let params = ChainParameters {
4894            parameters: Some(generated::chain_parameters::Parameters::V1(cpv1)),
4895        };
4896        let converted = crate::v2::ChainParameters::try_from(params)
4897            .expect("Failed to convert chain parameters v1");
4898        let expected = crate::v2::ChainParameters {
4899            timeout_parameters: Default::default(),
4900            election_difficulty: Some(base::ElectionDifficulty::new_unchecked(21111)),
4901            min_block_time: None,
4902            block_energy_limit: None,
4903            euro_per_energy: Some(base::ExchangeRate::new_unchecked(2, 3)),
4904            micro_ccd_per_euro: Some(base::ExchangeRate::new_unchecked(4, 5)),
4905            cooldown_parameters: chain_parameters::CooldownParameters {
4906                baker_cooldown_epochs: None,
4907                pool_owner_cooldown: Some(base::DurationSeconds::from(6)),
4908                delegator_cooldown: Some(base::DurationSeconds::from(7)),
4909            },
4910            reward_period_length: Some(updates::RewardPeriodLength::from(base::Epoch::from(8))),
4911            mint_per_payday: Some(base::MintRate {
4912                mantissa: 9,
4913                exponent: 10,
4914            }),
4915            mint_per_slot: None,
4916            account_creation_limit: Some(base::CredentialsPerBlockLimit::from(11)),
4917            mint_distribution: chain_parameters::MintDistribution {
4918                baking_reward: Some(base::AmountFraction::new_unchecked(12)),
4919                finalization_reward: Some(base::AmountFraction::new_unchecked(13)),
4920            },
4921            transaction_fee_distribution: chain_parameters::TransactionFeeDistribution {
4922                baker: Some(base::AmountFraction::new_unchecked(14)),
4923                gas_account: Some(base::AmountFraction::new_unchecked(15)),
4924            },
4925            gas_rewards: chain_parameters::GasRewards {
4926                baker: Some(base::AmountFraction::new_unchecked(16)),
4927                finalization_proof: Some(base::AmountFraction::new_unchecked(17)),
4928                account_creation: Some(base::AmountFraction::new_unchecked(18)),
4929                chain_update: Some(base::AmountFraction::new_unchecked(19)),
4930            },
4931            foundation_account: Some(contracts_common::AccountAddress([20u8; 32])),
4932            staking_parameters: chain_parameters::StakingParameters {
4933                passive_finalization_commission: Some(base::AmountFraction::new_unchecked(21)),
4934                passive_baking_commission: Some(base::AmountFraction::new_unchecked(22)),
4935                passive_transaction_commission: Some(base::AmountFraction::new_unchecked(23)),
4936                finalization_commission_range: Some(base::InclusiveRange {
4937                    min: base::AmountFraction::new_unchecked(24),
4938                    max: base::AmountFraction::new_unchecked(25),
4939                }),
4940                baking_commission_range: Some(base::InclusiveRange {
4941                    min: base::AmountFraction::new_unchecked(26),
4942                    max: base::AmountFraction::new_unchecked(27),
4943                }),
4944                transaction_commission_range: Some(base::InclusiveRange {
4945                    min: base::AmountFraction::new_unchecked(28),
4946                    max: base::AmountFraction::new_unchecked(29),
4947                }),
4948                minimum_equity_capital: Some(contracts_common::Amount::from_micro_ccd(30)),
4949                capital_bound: Some(base::CapitalBound {
4950                    bound: base::AmountFraction::new_unchecked(31),
4951                }),
4952                leverage_bound: Some(base::LeverageFactor {
4953                    numerator: 33,
4954                    denominator: 32,
4955                }),
4956            },
4957            finalization_committee_parameters: Default::default(),
4958            validator_max_missed_rounds: None,
4959            keys: chain_parameters::UpdateKeys {
4960                root_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
4961                    concordium_base::updates::RootKeysKind,
4962                > {
4963                    keys: vec![base::UpdatePublicKey::from(
4964                        crate::id::types::VerifyKey::from(root_key),
4965                    )],
4966                    threshold: 34.try_into().unwrap(),
4967                    _phantom: Default::default(),
4968                }),
4969                level_1_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
4970                    concordium_base::updates::Level1KeysKind,
4971                > {
4972                    keys: vec![base::UpdatePublicKey::from(
4973                        crate::id::types::VerifyKey::from(level_1_key),
4974                    )],
4975                    threshold: 35.try_into().unwrap(),
4976                    _phantom: Default::default(),
4977                }),
4978                level_2_keys: Some(chain_parameters::Level2Keys {
4979                    keys: vec![
4980                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
4981                            level_2_key_1,
4982                        )),
4983                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
4984                            level_2_key_2,
4985                        )),
4986                    ],
4987                    emergency: Some(updates::AccessStructure {
4988                        authorized_keys: [base::UpdateKeysIndex::from(113)].into(),
4989                        threshold: 127.try_into().unwrap(),
4990                    }),
4991                    protocol: Some(updates::AccessStructure {
4992                        authorized_keys: [base::UpdateKeysIndex::from(131)].into(),
4993                        threshold: 137.try_into().unwrap(),
4994                    }),
4995                    consensus: Some(updates::AccessStructure {
4996                        authorized_keys: [base::UpdateKeysIndex::from(139)].into(),
4997                        threshold: 149.try_into().unwrap(),
4998                    }),
4999                    euro_per_energy: Some(updates::AccessStructure {
5000                        authorized_keys: [base::UpdateKeysIndex::from(151)].into(),
5001                        threshold: 157.try_into().unwrap(),
5002                    }),
5003                    micro_ccd_per_euro: Some(updates::AccessStructure {
5004                        authorized_keys: [base::UpdateKeysIndex::from(173)].into(),
5005                        threshold: 179.try_into().unwrap(),
5006                    }),
5007                    foundation_account: Some(updates::AccessStructure {
5008                        authorized_keys: [base::UpdateKeysIndex::from(181)].into(),
5009                        threshold: 191.try_into().unwrap(),
5010                    }),
5011                    mint_distribution: Some(updates::AccessStructure {
5012                        authorized_keys: [base::UpdateKeysIndex::from(193)].into(),
5013                        threshold: 197.try_into().unwrap(),
5014                    }),
5015                    transaction_fee_distribution: Some(updates::AccessStructure {
5016                        authorized_keys: [base::UpdateKeysIndex::from(199)].into(),
5017                        threshold: 211.try_into().unwrap(),
5018                    }),
5019                    param_gas_rewards: Some(updates::AccessStructure {
5020                        authorized_keys: [base::UpdateKeysIndex::from(223)].into(),
5021                        threshold: 227.try_into().unwrap(),
5022                    }),
5023                    pool_parameters: Some(updates::AccessStructure {
5024                        authorized_keys: [base::UpdateKeysIndex::from(229)].into(),
5025                        threshold: 233.try_into().unwrap(),
5026                    }),
5027                    add_anonymity_revoker: Some(updates::AccessStructure {
5028                        authorized_keys: [base::UpdateKeysIndex::from(239)].into(),
5029                        threshold: 241.try_into().unwrap(),
5030                    }),
5031                    add_identity_provider: Some(updates::AccessStructure {
5032                        authorized_keys: [base::UpdateKeysIndex::from(251)].into(),
5033                        threshold: 257.try_into().unwrap(),
5034                    }),
5035                    cooldown_parameters: Some(updates::AccessStructure {
5036                        authorized_keys: [base::UpdateKeysIndex::from(263)].into(),
5037                        threshold: 269.try_into().unwrap(),
5038                    }),
5039                    time_parameters: Some(updates::AccessStructure {
5040                        authorized_keys: [base::UpdateKeysIndex::from(271)].into(),
5041                        threshold: 277.try_into().unwrap(),
5042                    }),
5043                    create_plt: None,
5044                }),
5045            },
5046        };
5047        assert_eq!(converted, expected);
5048    }
5049
5050    #[test]
5051    fn test_try_from_chain_parameters_v2() {
5052        let mut rng = StdRng::seed_from_u64(1);
5053        let (root_key, root_key_bytes) = gen_public_key(&mut rng);
5054        let (level_1_key, level_1_key_bytes) = gen_public_key(&mut rng);
5055        let (level_2_key_1, level_2_key_1_bytes) = gen_public_key(&mut rng);
5056        let (level_2_key_2, level_2_key_2_bytes) = gen_public_key(&mut rng);
5057        let cpv2 = ChainParametersV2 {
5058            consensus_parameters: Some(ConsensusParametersV1 {
5059                timeout_parameters: Some(TimeoutParameters {
5060                    timeout_base: Some(Duration { value: 500 }),
5061                    timeout_increase: Some(Ratio {
5062                        numerator: 502,
5063                        denominator: 501,
5064                    }),
5065                    timeout_decrease: Some(Ratio {
5066                        numerator: 503,
5067                        denominator: 504,
5068                    }),
5069                }),
5070                min_block_time: Some(Duration { value: 505 }),
5071                block_energy_limit: Some(Energy { value: 506 }),
5072            }),
5073            euro_per_energy: Some(ExchangeRate {
5074                value: Some(Ratio {
5075                    numerator: 2,
5076                    denominator: 3,
5077                }),
5078            }),
5079            micro_ccd_per_euro: Some(ExchangeRate {
5080                value: Some(Ratio {
5081                    numerator: 4,
5082                    denominator: 5,
5083                }),
5084            }),
5085            cooldown_parameters: Some(CooldownParametersCpv1 {
5086                pool_owner_cooldown: Some(DurationSeconds { value: 6 }),
5087                delegator_cooldown: Some(DurationSeconds { value: 7 }),
5088            }),
5089            time_parameters: Some(TimeParametersCpv1 {
5090                reward_period_length: Some(RewardPeriodLength {
5091                    value: Some(Epoch { value: 8 }),
5092                }),
5093                mint_per_payday: Some(MintRate {
5094                    mantissa: 9,
5095                    exponent: 10,
5096                }),
5097            }),
5098            account_creation_limit: Some(CredentialsPerBlockLimit { value: 11 }),
5099            mint_distribution: Some(MintDistributionCpv1 {
5100                baking_reward: Some(AmountFraction {
5101                    parts_per_hundred_thousand: 12,
5102                }),
5103                finalization_reward: Some(AmountFraction {
5104                    parts_per_hundred_thousand: 13,
5105                }),
5106            }),
5107            transaction_fee_distribution: Some(TransactionFeeDistribution {
5108                baker: Some(AmountFraction {
5109                    parts_per_hundred_thousand: 14,
5110                }),
5111                gas_account: Some(AmountFraction {
5112                    parts_per_hundred_thousand: 15,
5113                }),
5114            }),
5115            gas_rewards: Some(GasRewardsCpv2 {
5116                baker: Some(AmountFraction {
5117                    parts_per_hundred_thousand: 16,
5118                }),
5119                account_creation: Some(AmountFraction {
5120                    parts_per_hundred_thousand: 18,
5121                }),
5122                chain_update: Some(AmountFraction {
5123                    parts_per_hundred_thousand: 19,
5124                }),
5125            }),
5126            foundation_account: Some(AccountAddress {
5127                value: vec![20u8; 32],
5128            }),
5129            pool_parameters: Some(PoolParametersCpv1 {
5130                passive_finalization_commission: Some(AmountFraction {
5131                    parts_per_hundred_thousand: 21,
5132                }),
5133                passive_baking_commission: Some(AmountFraction {
5134                    parts_per_hundred_thousand: 22,
5135                }),
5136                passive_transaction_commission: Some(AmountFraction {
5137                    parts_per_hundred_thousand: 23,
5138                }),
5139                commission_bounds: Some(CommissionRanges {
5140                    finalization: Some(InclusiveRangeAmountFraction {
5141                        min: Some(AmountFraction {
5142                            parts_per_hundred_thousand: 24,
5143                        }),
5144                        max: Some(AmountFraction {
5145                            parts_per_hundred_thousand: 25,
5146                        }),
5147                    }),
5148                    baking: Some(InclusiveRangeAmountFraction {
5149                        min: Some(AmountFraction {
5150                            parts_per_hundred_thousand: 26,
5151                        }),
5152                        max: Some(AmountFraction {
5153                            parts_per_hundred_thousand: 27,
5154                        }),
5155                    }),
5156                    transaction: Some(InclusiveRangeAmountFraction {
5157                        min: Some(AmountFraction {
5158                            parts_per_hundred_thousand: 28,
5159                        }),
5160                        max: Some(AmountFraction {
5161                            parts_per_hundred_thousand: 29,
5162                        }),
5163                    }),
5164                }),
5165                minimum_equity_capital: Some(Amount { value: 30 }),
5166                capital_bound: Some(CapitalBound {
5167                    value: Some(AmountFraction {
5168                        parts_per_hundred_thousand: 31,
5169                    }),
5170                }),
5171                leverage_bound: Some(LeverageFactor {
5172                    value: Some(Ratio {
5173                        numerator: 33,
5174                        denominator: 32,
5175                    }),
5176                }),
5177            }),
5178            root_keys: Some(HigherLevelKeys {
5179                keys: vec![UpdatePublicKey {
5180                    value: root_key_bytes,
5181                }],
5182                threshold: Some(UpdateKeysThreshold { value: 34 }),
5183            }),
5184            level1_keys: Some(HigherLevelKeys {
5185                keys: vec![UpdatePublicKey {
5186                    value: level_1_key_bytes,
5187                }],
5188                threshold: Some(UpdateKeysThreshold { value: 35 }),
5189            }),
5190            level2_keys: Some(AuthorizationsV1 {
5191                v0: Some(AuthorizationsV0 {
5192                    keys: vec![
5193                        UpdatePublicKey {
5194                            value: level_2_key_1_bytes,
5195                        },
5196                        UpdatePublicKey {
5197                            value: level_2_key_2_bytes,
5198                        },
5199                    ],
5200                    emergency: Some(AccessStructure {
5201                        access_public_keys: vec![UpdateKeysIndex { value: 113 }],
5202                        access_threshold: Some(UpdateKeysThreshold { value: 127 }),
5203                    }),
5204                    protocol: Some(AccessStructure {
5205                        access_public_keys: vec![UpdateKeysIndex { value: 131 }],
5206                        access_threshold: Some(UpdateKeysThreshold { value: 137 }),
5207                    }),
5208                    parameter_consensus: Some(AccessStructure {
5209                        access_public_keys: vec![UpdateKeysIndex { value: 139 }],
5210                        access_threshold: Some(UpdateKeysThreshold { value: 149 }),
5211                    }),
5212                    parameter_euro_per_energy: Some(AccessStructure {
5213                        access_public_keys: vec![UpdateKeysIndex { value: 151 }],
5214                        access_threshold: Some(UpdateKeysThreshold { value: 157 }),
5215                    }),
5216                    parameter_micro_ccd_per_euro: Some(AccessStructure {
5217                        access_public_keys: vec![UpdateKeysIndex { value: 173 }],
5218                        access_threshold: Some(UpdateKeysThreshold { value: 179 }),
5219                    }),
5220                    parameter_foundation_account: Some(AccessStructure {
5221                        access_public_keys: vec![UpdateKeysIndex { value: 181 }],
5222                        access_threshold: Some(UpdateKeysThreshold { value: 191 }),
5223                    }),
5224                    parameter_mint_distribution: Some(AccessStructure {
5225                        access_public_keys: vec![UpdateKeysIndex { value: 193 }],
5226                        access_threshold: Some(UpdateKeysThreshold { value: 197 }),
5227                    }),
5228                    parameter_transaction_fee_distribution: Some(AccessStructure {
5229                        access_public_keys: vec![UpdateKeysIndex { value: 199 }],
5230                        access_threshold: Some(UpdateKeysThreshold { value: 211 }),
5231                    }),
5232                    parameter_gas_rewards: Some(AccessStructure {
5233                        access_public_keys: vec![UpdateKeysIndex { value: 223 }],
5234                        access_threshold: Some(UpdateKeysThreshold { value: 227 }),
5235                    }),
5236                    pool_parameters: Some(AccessStructure {
5237                        access_public_keys: vec![UpdateKeysIndex { value: 229 }],
5238                        access_threshold: Some(UpdateKeysThreshold { value: 233 }),
5239                    }),
5240                    add_anonymity_revoker: Some(AccessStructure {
5241                        access_public_keys: vec![UpdateKeysIndex { value: 239 }],
5242                        access_threshold: Some(UpdateKeysThreshold { value: 241 }),
5243                    }),
5244                    add_identity_provider: Some(AccessStructure {
5245                        access_public_keys: vec![UpdateKeysIndex { value: 251 }],
5246                        access_threshold: Some(UpdateKeysThreshold { value: 257 }),
5247                    }),
5248                }),
5249                parameter_cooldown: Some(AccessStructure {
5250                    access_public_keys: vec![UpdateKeysIndex { value: 263 }],
5251                    access_threshold: Some(UpdateKeysThreshold { value: 269 }),
5252                }),
5253                parameter_time: Some(AccessStructure {
5254                    access_public_keys: vec![UpdateKeysIndex { value: 271 }],
5255                    access_threshold: Some(UpdateKeysThreshold { value: 277 }),
5256                }),
5257                create_plt: None,
5258            }),
5259            finalization_committee_parameters: Some(FinalizationCommitteeParameters {
5260                minimum_finalizers: 601,
5261                maximum_finalizers: 602,
5262                finalizer_relative_stake_threshold: Some(AmountFraction {
5263                    parts_per_hundred_thousand: 603,
5264                }),
5265            }),
5266        };
5267        let params = ChainParameters {
5268            parameters: Some(generated::chain_parameters::Parameters::V2(cpv2)),
5269        };
5270        let converted = crate::v2::ChainParameters::try_from(params)
5271            .expect("Failed to convert chain parameters v1");
5272        let expected = crate::v2::ChainParameters {
5273            timeout_parameters: chain_parameters::TimeoutParameters {
5274                base: Some(contracts_common::Duration::from_millis(500)),
5275                increase: Some(concordium_base::common::types::Ratio::new_unchecked(
5276                    502, 501,
5277                )),
5278                decrease: Some(concordium_base::common::types::Ratio::new_unchecked(
5279                    503, 504,
5280                )),
5281            },
5282            election_difficulty: None,
5283            min_block_time: Some(contracts_common::Duration::from_millis(505)),
5284            block_energy_limit: Some(base::Energy::from(506)),
5285            euro_per_energy: Some(base::ExchangeRate::new_unchecked(2, 3)),
5286            micro_ccd_per_euro: Some(base::ExchangeRate::new_unchecked(4, 5)),
5287            cooldown_parameters: chain_parameters::CooldownParameters {
5288                baker_cooldown_epochs: None,
5289                pool_owner_cooldown: Some(base::DurationSeconds::from(6)),
5290                delegator_cooldown: Some(base::DurationSeconds::from(7)),
5291            },
5292            reward_period_length: Some(updates::RewardPeriodLength::from(base::Epoch::from(8))),
5293            mint_per_payday: Some(base::MintRate {
5294                mantissa: 9,
5295                exponent: 10,
5296            }),
5297            mint_per_slot: None,
5298            account_creation_limit: Some(base::CredentialsPerBlockLimit::from(11)),
5299            mint_distribution: chain_parameters::MintDistribution {
5300                baking_reward: Some(base::AmountFraction::new_unchecked(12)),
5301                finalization_reward: Some(base::AmountFraction::new_unchecked(13)),
5302            },
5303            transaction_fee_distribution: chain_parameters::TransactionFeeDistribution {
5304                baker: Some(base::AmountFraction::new_unchecked(14)),
5305                gas_account: Some(base::AmountFraction::new_unchecked(15)),
5306            },
5307            gas_rewards: chain_parameters::GasRewards {
5308                baker: Some(base::AmountFraction::new_unchecked(16)),
5309                finalization_proof: None,
5310                account_creation: Some(base::AmountFraction::new_unchecked(18)),
5311                chain_update: Some(base::AmountFraction::new_unchecked(19)),
5312            },
5313            foundation_account: Some(contracts_common::AccountAddress([20u8; 32])),
5314            staking_parameters: chain_parameters::StakingParameters {
5315                passive_finalization_commission: Some(base::AmountFraction::new_unchecked(21)),
5316                passive_baking_commission: Some(base::AmountFraction::new_unchecked(22)),
5317                passive_transaction_commission: Some(base::AmountFraction::new_unchecked(23)),
5318                finalization_commission_range: Some(base::InclusiveRange {
5319                    min: base::AmountFraction::new_unchecked(24),
5320                    max: base::AmountFraction::new_unchecked(25),
5321                }),
5322                baking_commission_range: Some(base::InclusiveRange {
5323                    min: base::AmountFraction::new_unchecked(26),
5324                    max: base::AmountFraction::new_unchecked(27),
5325                }),
5326                transaction_commission_range: Some(base::InclusiveRange {
5327                    min: base::AmountFraction::new_unchecked(28),
5328                    max: base::AmountFraction::new_unchecked(29),
5329                }),
5330                minimum_equity_capital: Some(contracts_common::Amount::from_micro_ccd(30)),
5331                capital_bound: Some(base::CapitalBound {
5332                    bound: base::AmountFraction::new_unchecked(31),
5333                }),
5334                leverage_bound: Some(base::LeverageFactor {
5335                    numerator: 33,
5336                    denominator: 32,
5337                }),
5338            },
5339            finalization_committee_parameters: chain_parameters::FinalizationCommitteeParameters {
5340                min_finalizers: Some(601),
5341                max_finalizers: Some(602),
5342                finalizers_relative_stake_threshold: Some(PartsPerHundredThousands::new_unchecked(
5343                    603,
5344                )),
5345            },
5346            validator_max_missed_rounds: None,
5347            keys: chain_parameters::UpdateKeys {
5348                root_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
5349                    concordium_base::updates::RootKeysKind,
5350                > {
5351                    keys: vec![base::UpdatePublicKey::from(
5352                        crate::id::types::VerifyKey::from(root_key),
5353                    )],
5354                    threshold: 34.try_into().unwrap(),
5355                    _phantom: Default::default(),
5356                }),
5357                level_1_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
5358                    concordium_base::updates::Level1KeysKind,
5359                > {
5360                    keys: vec![base::UpdatePublicKey::from(
5361                        crate::id::types::VerifyKey::from(level_1_key),
5362                    )],
5363                    threshold: 35.try_into().unwrap(),
5364                    _phantom: Default::default(),
5365                }),
5366                level_2_keys: Some(chain_parameters::Level2Keys {
5367                    keys: vec![
5368                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
5369                            level_2_key_1,
5370                        )),
5371                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
5372                            level_2_key_2,
5373                        )),
5374                    ],
5375                    emergency: Some(updates::AccessStructure {
5376                        authorized_keys: [base::UpdateKeysIndex::from(113)].into(),
5377                        threshold: 127.try_into().unwrap(),
5378                    }),
5379                    protocol: Some(updates::AccessStructure {
5380                        authorized_keys: [base::UpdateKeysIndex::from(131)].into(),
5381                        threshold: 137.try_into().unwrap(),
5382                    }),
5383                    consensus: Some(updates::AccessStructure {
5384                        authorized_keys: [base::UpdateKeysIndex::from(139)].into(),
5385                        threshold: 149.try_into().unwrap(),
5386                    }),
5387                    euro_per_energy: Some(updates::AccessStructure {
5388                        authorized_keys: [base::UpdateKeysIndex::from(151)].into(),
5389                        threshold: 157.try_into().unwrap(),
5390                    }),
5391                    micro_ccd_per_euro: Some(updates::AccessStructure {
5392                        authorized_keys: [base::UpdateKeysIndex::from(173)].into(),
5393                        threshold: 179.try_into().unwrap(),
5394                    }),
5395                    foundation_account: Some(updates::AccessStructure {
5396                        authorized_keys: [base::UpdateKeysIndex::from(181)].into(),
5397                        threshold: 191.try_into().unwrap(),
5398                    }),
5399                    mint_distribution: Some(updates::AccessStructure {
5400                        authorized_keys: [base::UpdateKeysIndex::from(193)].into(),
5401                        threshold: 197.try_into().unwrap(),
5402                    }),
5403                    transaction_fee_distribution: Some(updates::AccessStructure {
5404                        authorized_keys: [base::UpdateKeysIndex::from(199)].into(),
5405                        threshold: 211.try_into().unwrap(),
5406                    }),
5407                    param_gas_rewards: Some(updates::AccessStructure {
5408                        authorized_keys: [base::UpdateKeysIndex::from(223)].into(),
5409                        threshold: 227.try_into().unwrap(),
5410                    }),
5411                    pool_parameters: Some(updates::AccessStructure {
5412                        authorized_keys: [base::UpdateKeysIndex::from(229)].into(),
5413                        threshold: 233.try_into().unwrap(),
5414                    }),
5415                    add_anonymity_revoker: Some(updates::AccessStructure {
5416                        authorized_keys: [base::UpdateKeysIndex::from(239)].into(),
5417                        threshold: 241.try_into().unwrap(),
5418                    }),
5419                    add_identity_provider: Some(updates::AccessStructure {
5420                        authorized_keys: [base::UpdateKeysIndex::from(251)].into(),
5421                        threshold: 257.try_into().unwrap(),
5422                    }),
5423                    cooldown_parameters: Some(updates::AccessStructure {
5424                        authorized_keys: [base::UpdateKeysIndex::from(263)].into(),
5425                        threshold: 269.try_into().unwrap(),
5426                    }),
5427                    time_parameters: Some(updates::AccessStructure {
5428                        authorized_keys: [base::UpdateKeysIndex::from(271)].into(),
5429                        threshold: 277.try_into().unwrap(),
5430                    }),
5431                    create_plt: None,
5432                }),
5433            },
5434        };
5435        assert_eq!(converted, expected);
5436    }
5437
5438    #[test]
5439    fn test_try_from_chain_parameters_v3() {
5440        let mut rng = StdRng::seed_from_u64(1);
5441        let (root_key, root_key_bytes) = gen_public_key(&mut rng);
5442        let (level_1_key, level_1_key_bytes) = gen_public_key(&mut rng);
5443        let (level_2_key_1, level_2_key_1_bytes) = gen_public_key(&mut rng);
5444        let (level_2_key_2, level_2_key_2_bytes) = gen_public_key(&mut rng);
5445        let cpv3 = ChainParametersV3 {
5446            consensus_parameters: Some(ConsensusParametersV1 {
5447                timeout_parameters: Some(TimeoutParameters {
5448                    timeout_base: Some(Duration { value: 500 }),
5449                    timeout_increase: Some(Ratio {
5450                        numerator: 502,
5451                        denominator: 501,
5452                    }),
5453                    timeout_decrease: Some(Ratio {
5454                        numerator: 503,
5455                        denominator: 504,
5456                    }),
5457                }),
5458                min_block_time: Some(Duration { value: 505 }),
5459                block_energy_limit: Some(Energy { value: 506 }),
5460            }),
5461            euro_per_energy: Some(ExchangeRate {
5462                value: Some(Ratio {
5463                    numerator: 2,
5464                    denominator: 3,
5465                }),
5466            }),
5467            micro_ccd_per_euro: Some(ExchangeRate {
5468                value: Some(Ratio {
5469                    numerator: 4,
5470                    denominator: 5,
5471                }),
5472            }),
5473            cooldown_parameters: Some(CooldownParametersCpv1 {
5474                pool_owner_cooldown: Some(DurationSeconds { value: 6 }),
5475                delegator_cooldown: Some(DurationSeconds { value: 7 }),
5476            }),
5477            time_parameters: Some(TimeParametersCpv1 {
5478                reward_period_length: Some(RewardPeriodLength {
5479                    value: Some(Epoch { value: 8 }),
5480                }),
5481                mint_per_payday: Some(MintRate {
5482                    mantissa: 9,
5483                    exponent: 10,
5484                }),
5485            }),
5486            account_creation_limit: Some(CredentialsPerBlockLimit { value: 11 }),
5487            mint_distribution: Some(MintDistributionCpv1 {
5488                baking_reward: Some(AmountFraction {
5489                    parts_per_hundred_thousand: 12,
5490                }),
5491                finalization_reward: Some(AmountFraction {
5492                    parts_per_hundred_thousand: 13,
5493                }),
5494            }),
5495            transaction_fee_distribution: Some(TransactionFeeDistribution {
5496                baker: Some(AmountFraction {
5497                    parts_per_hundred_thousand: 14,
5498                }),
5499                gas_account: Some(AmountFraction {
5500                    parts_per_hundred_thousand: 15,
5501                }),
5502            }),
5503            gas_rewards: Some(GasRewardsCpv2 {
5504                baker: Some(AmountFraction {
5505                    parts_per_hundred_thousand: 16,
5506                }),
5507                account_creation: Some(AmountFraction {
5508                    parts_per_hundred_thousand: 18,
5509                }),
5510                chain_update: Some(AmountFraction {
5511                    parts_per_hundred_thousand: 19,
5512                }),
5513            }),
5514            foundation_account: Some(AccountAddress {
5515                value: vec![20u8; 32],
5516            }),
5517            pool_parameters: Some(PoolParametersCpv1 {
5518                passive_finalization_commission: Some(AmountFraction {
5519                    parts_per_hundred_thousand: 21,
5520                }),
5521                passive_baking_commission: Some(AmountFraction {
5522                    parts_per_hundred_thousand: 22,
5523                }),
5524                passive_transaction_commission: Some(AmountFraction {
5525                    parts_per_hundred_thousand: 23,
5526                }),
5527                commission_bounds: Some(CommissionRanges {
5528                    finalization: Some(InclusiveRangeAmountFraction {
5529                        min: Some(AmountFraction {
5530                            parts_per_hundred_thousand: 24,
5531                        }),
5532                        max: Some(AmountFraction {
5533                            parts_per_hundred_thousand: 25,
5534                        }),
5535                    }),
5536                    baking: Some(InclusiveRangeAmountFraction {
5537                        min: Some(AmountFraction {
5538                            parts_per_hundred_thousand: 26,
5539                        }),
5540                        max: Some(AmountFraction {
5541                            parts_per_hundred_thousand: 27,
5542                        }),
5543                    }),
5544                    transaction: Some(InclusiveRangeAmountFraction {
5545                        min: Some(AmountFraction {
5546                            parts_per_hundred_thousand: 28,
5547                        }),
5548                        max: Some(AmountFraction {
5549                            parts_per_hundred_thousand: 29,
5550                        }),
5551                    }),
5552                }),
5553                minimum_equity_capital: Some(Amount { value: 30 }),
5554                capital_bound: Some(CapitalBound {
5555                    value: Some(AmountFraction {
5556                        parts_per_hundred_thousand: 31,
5557                    }),
5558                }),
5559                leverage_bound: Some(LeverageFactor {
5560                    value: Some(Ratio {
5561                        numerator: 33,
5562                        denominator: 32,
5563                    }),
5564                }),
5565            }),
5566            root_keys: Some(HigherLevelKeys {
5567                keys: vec![UpdatePublicKey {
5568                    value: root_key_bytes,
5569                }],
5570                threshold: Some(UpdateKeysThreshold { value: 34 }),
5571            }),
5572            level1_keys: Some(HigherLevelKeys {
5573                keys: vec![UpdatePublicKey {
5574                    value: level_1_key_bytes,
5575                }],
5576                threshold: Some(UpdateKeysThreshold { value: 35 }),
5577            }),
5578            level2_keys: Some(AuthorizationsV1 {
5579                v0: Some(AuthorizationsV0 {
5580                    keys: vec![
5581                        UpdatePublicKey {
5582                            value: level_2_key_1_bytes,
5583                        },
5584                        UpdatePublicKey {
5585                            value: level_2_key_2_bytes,
5586                        },
5587                    ],
5588                    emergency: Some(AccessStructure {
5589                        access_public_keys: vec![UpdateKeysIndex { value: 113 }],
5590                        access_threshold: Some(UpdateKeysThreshold { value: 127 }),
5591                    }),
5592                    protocol: Some(AccessStructure {
5593                        access_public_keys: vec![UpdateKeysIndex { value: 131 }],
5594                        access_threshold: Some(UpdateKeysThreshold { value: 137 }),
5595                    }),
5596                    parameter_consensus: Some(AccessStructure {
5597                        access_public_keys: vec![UpdateKeysIndex { value: 139 }],
5598                        access_threshold: Some(UpdateKeysThreshold { value: 149 }),
5599                    }),
5600                    parameter_euro_per_energy: Some(AccessStructure {
5601                        access_public_keys: vec![UpdateKeysIndex { value: 151 }],
5602                        access_threshold: Some(UpdateKeysThreshold { value: 157 }),
5603                    }),
5604                    parameter_micro_ccd_per_euro: Some(AccessStructure {
5605                        access_public_keys: vec![UpdateKeysIndex { value: 173 }],
5606                        access_threshold: Some(UpdateKeysThreshold { value: 179 }),
5607                    }),
5608                    parameter_foundation_account: Some(AccessStructure {
5609                        access_public_keys: vec![UpdateKeysIndex { value: 181 }],
5610                        access_threshold: Some(UpdateKeysThreshold { value: 191 }),
5611                    }),
5612                    parameter_mint_distribution: Some(AccessStructure {
5613                        access_public_keys: vec![UpdateKeysIndex { value: 193 }],
5614                        access_threshold: Some(UpdateKeysThreshold { value: 197 }),
5615                    }),
5616                    parameter_transaction_fee_distribution: Some(AccessStructure {
5617                        access_public_keys: vec![UpdateKeysIndex { value: 199 }],
5618                        access_threshold: Some(UpdateKeysThreshold { value: 211 }),
5619                    }),
5620                    parameter_gas_rewards: Some(AccessStructure {
5621                        access_public_keys: vec![UpdateKeysIndex { value: 223 }],
5622                        access_threshold: Some(UpdateKeysThreshold { value: 227 }),
5623                    }),
5624                    pool_parameters: Some(AccessStructure {
5625                        access_public_keys: vec![UpdateKeysIndex { value: 229 }],
5626                        access_threshold: Some(UpdateKeysThreshold { value: 233 }),
5627                    }),
5628                    add_anonymity_revoker: Some(AccessStructure {
5629                        access_public_keys: vec![UpdateKeysIndex { value: 239 }],
5630                        access_threshold: Some(UpdateKeysThreshold { value: 241 }),
5631                    }),
5632                    add_identity_provider: Some(AccessStructure {
5633                        access_public_keys: vec![UpdateKeysIndex { value: 251 }],
5634                        access_threshold: Some(UpdateKeysThreshold { value: 257 }),
5635                    }),
5636                }),
5637                parameter_cooldown: Some(AccessStructure {
5638                    access_public_keys: vec![UpdateKeysIndex { value: 263 }],
5639                    access_threshold: Some(UpdateKeysThreshold { value: 269 }),
5640                }),
5641                parameter_time: Some(AccessStructure {
5642                    access_public_keys: vec![UpdateKeysIndex { value: 271 }],
5643                    access_threshold: Some(UpdateKeysThreshold { value: 277 }),
5644                }),
5645                create_plt: Some(AccessStructure {
5646                    access_public_keys: vec![
5647                        UpdateKeysIndex { value: 281 },
5648                        UpdateKeysIndex { value: 283 },
5649                    ],
5650                    access_threshold: Some(UpdateKeysThreshold { value: 293 }),
5651                }),
5652            }),
5653            finalization_committee_parameters: Some(FinalizationCommitteeParameters {
5654                minimum_finalizers: 601,
5655                maximum_finalizers: 602,
5656                finalizer_relative_stake_threshold: Some(AmountFraction {
5657                    parts_per_hundred_thousand: 603,
5658                }),
5659            }),
5660            validator_score_parameters: Some(ValidatorScoreParameters {
5661                maximum_missed_rounds: 607,
5662            }),
5663        };
5664        let params = ChainParameters {
5665            parameters: Some(generated::chain_parameters::Parameters::V3(cpv3)),
5666        };
5667        let converted = crate::v2::ChainParameters::try_from(params)
5668            .expect("Failed to convert chain parameters v1");
5669        let expected = crate::v2::ChainParameters {
5670            timeout_parameters: chain_parameters::TimeoutParameters {
5671                base: Some(contracts_common::Duration::from_millis(500)),
5672                increase: Some(concordium_base::common::types::Ratio::new_unchecked(
5673                    502, 501,
5674                )),
5675                decrease: Some(concordium_base::common::types::Ratio::new_unchecked(
5676                    503, 504,
5677                )),
5678            },
5679            election_difficulty: None,
5680            min_block_time: Some(contracts_common::Duration::from_millis(505)),
5681            block_energy_limit: Some(base::Energy::from(506)),
5682            euro_per_energy: Some(base::ExchangeRate::new_unchecked(2, 3)),
5683            micro_ccd_per_euro: Some(base::ExchangeRate::new_unchecked(4, 5)),
5684            cooldown_parameters: chain_parameters::CooldownParameters {
5685                baker_cooldown_epochs: None,
5686                pool_owner_cooldown: Some(base::DurationSeconds::from(6)),
5687                delegator_cooldown: Some(base::DurationSeconds::from(7)),
5688            },
5689            reward_period_length: Some(updates::RewardPeriodLength::from(base::Epoch::from(8))),
5690            mint_per_payday: Some(base::MintRate {
5691                mantissa: 9,
5692                exponent: 10,
5693            }),
5694            mint_per_slot: None,
5695            account_creation_limit: Some(base::CredentialsPerBlockLimit::from(11)),
5696            mint_distribution: chain_parameters::MintDistribution {
5697                baking_reward: Some(base::AmountFraction::new_unchecked(12)),
5698                finalization_reward: Some(base::AmountFraction::new_unchecked(13)),
5699            },
5700            transaction_fee_distribution: chain_parameters::TransactionFeeDistribution {
5701                baker: Some(base::AmountFraction::new_unchecked(14)),
5702                gas_account: Some(base::AmountFraction::new_unchecked(15)),
5703            },
5704            gas_rewards: chain_parameters::GasRewards {
5705                baker: Some(base::AmountFraction::new_unchecked(16)),
5706                finalization_proof: None,
5707                account_creation: Some(base::AmountFraction::new_unchecked(18)),
5708                chain_update: Some(base::AmountFraction::new_unchecked(19)),
5709            },
5710            foundation_account: Some(contracts_common::AccountAddress([20u8; 32])),
5711            staking_parameters: chain_parameters::StakingParameters {
5712                passive_finalization_commission: Some(base::AmountFraction::new_unchecked(21)),
5713                passive_baking_commission: Some(base::AmountFraction::new_unchecked(22)),
5714                passive_transaction_commission: Some(base::AmountFraction::new_unchecked(23)),
5715                finalization_commission_range: Some(base::InclusiveRange {
5716                    min: base::AmountFraction::new_unchecked(24),
5717                    max: base::AmountFraction::new_unchecked(25),
5718                }),
5719                baking_commission_range: Some(base::InclusiveRange {
5720                    min: base::AmountFraction::new_unchecked(26),
5721                    max: base::AmountFraction::new_unchecked(27),
5722                }),
5723                transaction_commission_range: Some(base::InclusiveRange {
5724                    min: base::AmountFraction::new_unchecked(28),
5725                    max: base::AmountFraction::new_unchecked(29),
5726                }),
5727                minimum_equity_capital: Some(contracts_common::Amount::from_micro_ccd(30)),
5728                capital_bound: Some(base::CapitalBound {
5729                    bound: base::AmountFraction::new_unchecked(31),
5730                }),
5731                leverage_bound: Some(base::LeverageFactor {
5732                    numerator: 33,
5733                    denominator: 32,
5734                }),
5735            },
5736            finalization_committee_parameters: chain_parameters::FinalizationCommitteeParameters {
5737                min_finalizers: Some(601),
5738                max_finalizers: Some(602),
5739                finalizers_relative_stake_threshold: Some(PartsPerHundredThousands::new_unchecked(
5740                    603,
5741                )),
5742            },
5743            validator_max_missed_rounds: Some(607),
5744            keys: chain_parameters::UpdateKeys {
5745                root_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
5746                    concordium_base::updates::RootKeysKind,
5747                > {
5748                    keys: vec![base::UpdatePublicKey::from(
5749                        crate::id::types::VerifyKey::from(root_key),
5750                    )],
5751                    threshold: 34.try_into().unwrap(),
5752                    _phantom: Default::default(),
5753                }),
5754                level_1_keys: Some(concordium_base::updates::HigherLevelAccessStructure::<
5755                    concordium_base::updates::Level1KeysKind,
5756                > {
5757                    keys: vec![base::UpdatePublicKey::from(
5758                        crate::id::types::VerifyKey::from(level_1_key),
5759                    )],
5760                    threshold: 35.try_into().unwrap(),
5761                    _phantom: Default::default(),
5762                }),
5763                level_2_keys: Some(chain_parameters::Level2Keys {
5764                    keys: vec![
5765                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
5766                            level_2_key_1,
5767                        )),
5768                        base::UpdatePublicKey::from(crate::id::types::VerifyKey::from(
5769                            level_2_key_2,
5770                        )),
5771                    ],
5772                    emergency: Some(updates::AccessStructure {
5773                        authorized_keys: [base::UpdateKeysIndex::from(113)].into(),
5774                        threshold: 127.try_into().unwrap(),
5775                    }),
5776                    protocol: Some(updates::AccessStructure {
5777                        authorized_keys: [base::UpdateKeysIndex::from(131)].into(),
5778                        threshold: 137.try_into().unwrap(),
5779                    }),
5780                    consensus: Some(updates::AccessStructure {
5781                        authorized_keys: [base::UpdateKeysIndex::from(139)].into(),
5782                        threshold: 149.try_into().unwrap(),
5783                    }),
5784                    euro_per_energy: Some(updates::AccessStructure {
5785                        authorized_keys: [base::UpdateKeysIndex::from(151)].into(),
5786                        threshold: 157.try_into().unwrap(),
5787                    }),
5788                    micro_ccd_per_euro: Some(updates::AccessStructure {
5789                        authorized_keys: [base::UpdateKeysIndex::from(173)].into(),
5790                        threshold: 179.try_into().unwrap(),
5791                    }),
5792                    foundation_account: Some(updates::AccessStructure {
5793                        authorized_keys: [base::UpdateKeysIndex::from(181)].into(),
5794                        threshold: 191.try_into().unwrap(),
5795                    }),
5796                    mint_distribution: Some(updates::AccessStructure {
5797                        authorized_keys: [base::UpdateKeysIndex::from(193)].into(),
5798                        threshold: 197.try_into().unwrap(),
5799                    }),
5800                    transaction_fee_distribution: Some(updates::AccessStructure {
5801                        authorized_keys: [base::UpdateKeysIndex::from(199)].into(),
5802                        threshold: 211.try_into().unwrap(),
5803                    }),
5804                    param_gas_rewards: Some(updates::AccessStructure {
5805                        authorized_keys: [base::UpdateKeysIndex::from(223)].into(),
5806                        threshold: 227.try_into().unwrap(),
5807                    }),
5808                    pool_parameters: Some(updates::AccessStructure {
5809                        authorized_keys: [base::UpdateKeysIndex::from(229)].into(),
5810                        threshold: 233.try_into().unwrap(),
5811                    }),
5812                    add_anonymity_revoker: Some(updates::AccessStructure {
5813                        authorized_keys: [base::UpdateKeysIndex::from(239)].into(),
5814                        threshold: 241.try_into().unwrap(),
5815                    }),
5816                    add_identity_provider: Some(updates::AccessStructure {
5817                        authorized_keys: [base::UpdateKeysIndex::from(251)].into(),
5818                        threshold: 257.try_into().unwrap(),
5819                    }),
5820                    cooldown_parameters: Some(updates::AccessStructure {
5821                        authorized_keys: [base::UpdateKeysIndex::from(263)].into(),
5822                        threshold: 269.try_into().unwrap(),
5823                    }),
5824                    time_parameters: Some(updates::AccessStructure {
5825                        authorized_keys: [base::UpdateKeysIndex::from(271)].into(),
5826                        threshold: 277.try_into().unwrap(),
5827                    }),
5828                    create_plt: Some(updates::AccessStructure {
5829                        authorized_keys: [
5830                            base::UpdateKeysIndex::from(281),
5831                            base::UpdateKeysIndex::from(283),
5832                        ]
5833                        .into(),
5834                        threshold: 293.try_into().unwrap(),
5835                    }),
5836                }),
5837            },
5838        };
5839        assert_eq!(converted, expected);
5840    }
5841}