Skip to main content

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