pallas_primitives/conway/
model.rs

1//! Ledger primitives and cbor codec for the Conway era
2//!
3//! Handcrafted, idiomatic rust artifacts based on based on the [Conway CDDL](https://github.com/IntersectMBO/cardano-ledger/blob/master/eras/conway/impl/cddl-files/conway.cddl) file in IntersectMBO repo.
4
5use serde::{Deserialize, Serialize};
6
7use pallas_codec::minicbor::{self, Decode, Encode};
8use pallas_codec::utils::CborWrap;
9
10pub use crate::{
11    plutus_data::*, AddrKeyhash, AssetName, Bytes, Coin, CostModel, DnsName, Epoch, ExUnits,
12    GenesisDelegateHash, Genesishash, Hash, IPv4, IPv6, KeepRaw, KeyValuePairs, MaybeIndefArray,
13    Metadata, Metadatum, MetadatumLabel, NetworkId, NonEmptyKeyValuePairs, NonEmptySet, NonZeroInt,
14    Nonce, NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash, PoolMetadata,
15    PoolMetadataHash, Port, PositiveCoin, PositiveInterval, ProtocolVersion, RationalNumber, Relay,
16    RewardAccount, ScriptHash, Set, StakeCredential, TransactionIndex, TransactionInput,
17    UnitInterval, VrfCert, VrfKeyhash,
18};
19
20use crate::babbage;
21
22pub use crate::babbage::HeaderBody;
23
24pub use crate::babbage::OperationalCert;
25
26pub use crate::babbage::Header;
27
28pub type Multiasset<A> = NonEmptyKeyValuePairs<PolicyId, NonEmptyKeyValuePairs<AssetName, A>>;
29
30pub type Mint = Multiasset<NonZeroInt>;
31
32#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
33pub enum Value {
34    Coin(Coin),
35    Multiasset(Coin, Multiasset<PositiveCoin>),
36}
37
38impl<'b, C> minicbor::decode::Decode<'b, C> for Value {
39    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
40        match d.datatype()? {
41            minicbor::data::Type::U8 => Ok(Value::Coin(d.decode_with(ctx)?)),
42            minicbor::data::Type::U16 => Ok(Value::Coin(d.decode_with(ctx)?)),
43            minicbor::data::Type::U32 => Ok(Value::Coin(d.decode_with(ctx)?)),
44            minicbor::data::Type::U64 => Ok(Value::Coin(d.decode_with(ctx)?)),
45            minicbor::data::Type::Array => {
46                d.array()?;
47                let coin = d.decode_with(ctx)?;
48                let multiasset = d.decode_with(ctx)?;
49                Ok(Value::Multiasset(coin, multiasset))
50            }
51            _ => Err(minicbor::decode::Error::message(
52                "unknown cbor data type for Alonzo Value enum",
53            )),
54        }
55    }
56}
57
58impl<C> minicbor::encode::Encode<C> for Value {
59    fn encode<W: minicbor::encode::Write>(
60        &self,
61        e: &mut minicbor::Encoder<W>,
62        ctx: &mut C,
63    ) -> Result<(), minicbor::encode::Error<W::Error>> {
64        // TODO: check how to deal with uint variants (u32 vs u64)
65        match self {
66            Value::Coin(coin) => {
67                e.encode_with(coin, ctx)?;
68            }
69            Value::Multiasset(coin, other) => {
70                e.array(2)?;
71                e.encode_with(coin, ctx)?;
72                e.encode_with(other, ctx)?;
73            }
74        };
75
76        Ok(())
77    }
78}
79
80pub use crate::alonzo::TransactionOutput as LegacyTransactionOutput;
81
82pub type Withdrawals = NonEmptyKeyValuePairs<RewardAccount, Coin>;
83
84pub type RequiredSigners = NonEmptySet<AddrKeyhash>;
85
86#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
87pub enum Certificate {
88    StakeRegistration(StakeCredential),
89    StakeDeregistration(StakeCredential),
90    StakeDelegation(StakeCredential, PoolKeyhash),
91    PoolRegistration {
92        operator: PoolKeyhash,
93        vrf_keyhash: VrfKeyhash,
94        pledge: Coin,
95        cost: Coin,
96        margin: UnitInterval,
97        reward_account: RewardAccount,
98        pool_owners: Set<AddrKeyhash>,
99        relays: Vec<Relay>,
100        pool_metadata: Nullable<PoolMetadata>,
101    },
102    PoolRetirement(PoolKeyhash, Epoch),
103
104    Reg(StakeCredential, Coin),
105    UnReg(StakeCredential, Coin),
106    VoteDeleg(StakeCredential, DRep),
107    StakeVoteDeleg(StakeCredential, PoolKeyhash, DRep),
108    StakeRegDeleg(StakeCredential, PoolKeyhash, Coin),
109    VoteRegDeleg(StakeCredential, DRep, Coin),
110    StakeVoteRegDeleg(StakeCredential, PoolKeyhash, DRep, Coin),
111
112    AuthCommitteeHot(CommitteeColdCredential, CommitteeHotCredential),
113    ResignCommitteeCold(CommitteeColdCredential, Nullable<Anchor>),
114    RegDRepCert(DRepCredential, Coin, Nullable<Anchor>),
115    UnRegDRepCert(DRepCredential, Coin),
116    UpdateDRepCert(DRepCredential, Nullable<Anchor>),
117}
118
119impl<'b, C> minicbor::decode::Decode<'b, C> for Certificate {
120    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
121        d.array()?;
122        let variant = d.u16()?;
123
124        match variant {
125            0 => {
126                let a = d.decode_with(ctx)?;
127                Ok(Certificate::StakeRegistration(a))
128            }
129            1 => {
130                let a = d.decode_with(ctx)?;
131                Ok(Certificate::StakeDeregistration(a))
132            }
133            2 => {
134                let a = d.decode_with(ctx)?;
135                let b = d.decode_with(ctx)?;
136                Ok(Certificate::StakeDelegation(a, b))
137            }
138            3 => {
139                let operator = d.decode_with(ctx)?;
140                let vrf_keyhash = d.decode_with(ctx)?;
141                let pledge = d.decode_with(ctx)?;
142                let cost = d.decode_with(ctx)?;
143                let margin = d.decode_with(ctx)?;
144                let reward_account = d.decode_with(ctx)?;
145                let pool_owners = d.decode_with(ctx)?;
146                let relays = d.decode_with(ctx)?;
147                let pool_metadata = d.decode_with(ctx)?;
148
149                Ok(Certificate::PoolRegistration {
150                    operator,
151                    vrf_keyhash,
152                    pledge,
153                    cost,
154                    margin,
155                    reward_account,
156                    pool_owners,
157                    relays,
158                    pool_metadata,
159                })
160            }
161            4 => {
162                let a = d.decode_with(ctx)?;
163                let b = d.decode_with(ctx)?;
164                Ok(Certificate::PoolRetirement(a, b))
165            }
166
167            7 => {
168                let a = d.decode_with(ctx)?;
169                let b = d.decode_with(ctx)?;
170                Ok(Certificate::Reg(a, b))
171            }
172            8 => {
173                let a = d.decode_with(ctx)?;
174                let b = d.decode_with(ctx)?;
175                Ok(Certificate::UnReg(a, b))
176            }
177            9 => {
178                let a = d.decode_with(ctx)?;
179                let b = d.decode_with(ctx)?;
180                Ok(Certificate::VoteDeleg(a, b))
181            }
182            10 => {
183                let a = d.decode_with(ctx)?;
184                let b = d.decode_with(ctx)?;
185                let c = d.decode_with(ctx)?;
186                Ok(Certificate::StakeVoteDeleg(a, b, c))
187            }
188            11 => {
189                let a = d.decode_with(ctx)?;
190                let b = d.decode_with(ctx)?;
191                let c = d.decode_with(ctx)?;
192                Ok(Certificate::StakeRegDeleg(a, b, c))
193            }
194            12 => {
195                let a = d.decode_with(ctx)?;
196                let b = d.decode_with(ctx)?;
197                let c = d.decode_with(ctx)?;
198                Ok(Certificate::VoteRegDeleg(a, b, c))
199            }
200            13 => {
201                let a = d.decode_with(ctx)?;
202                let b = d.decode_with(ctx)?;
203                let c = d.decode_with(ctx)?;
204                let d = d.decode_with(ctx)?;
205                Ok(Certificate::StakeVoteRegDeleg(a, b, c, d))
206            }
207            14 => {
208                let a = d.decode_with(ctx)?;
209                let b = d.decode_with(ctx)?;
210                Ok(Certificate::AuthCommitteeHot(a, b))
211            }
212            15 => {
213                let a = d.decode_with(ctx)?;
214                let b = d.decode_with(ctx)?;
215                Ok(Certificate::ResignCommitteeCold(a, b))
216            }
217            16 => {
218                let a = d.decode_with(ctx)?;
219                let b = d.decode_with(ctx)?;
220                let c = d.decode_with(ctx)?;
221                Ok(Certificate::RegDRepCert(a, b, c))
222            }
223            17 => {
224                let a = d.decode_with(ctx)?;
225                let b = d.decode_with(ctx)?;
226                Ok(Certificate::UnRegDRepCert(a, b))
227            }
228            18 => {
229                let a = d.decode_with(ctx)?;
230                let b = d.decode_with(ctx)?;
231                Ok(Certificate::UpdateDRepCert(a, b))
232            }
233            _ => Err(minicbor::decode::Error::message(
234                "unknown variant id for certificate",
235            )),
236        }
237    }
238}
239
240impl<C> minicbor::encode::Encode<C> for Certificate {
241    fn encode<W: minicbor::encode::Write>(
242        &self,
243        e: &mut minicbor::Encoder<W>,
244        ctx: &mut C,
245    ) -> Result<(), minicbor::encode::Error<W::Error>> {
246        match self {
247            Certificate::StakeRegistration(a) => {
248                e.array(2)?;
249                e.u16(0)?;
250                e.encode_with(a, ctx)?;
251            }
252            Certificate::StakeDeregistration(a) => {
253                e.array(2)?;
254                e.u16(1)?;
255                e.encode_with(a, ctx)?;
256            }
257            Certificate::StakeDelegation(a, b) => {
258                e.array(3)?;
259                e.u16(2)?;
260                e.encode_with(a, ctx)?;
261                e.encode_with(b, ctx)?;
262            }
263            Certificate::PoolRegistration {
264                operator,
265                vrf_keyhash,
266                pledge,
267                cost,
268                margin,
269                reward_account,
270                pool_owners,
271                relays,
272                pool_metadata,
273            } => {
274                e.array(10)?;
275                e.u16(3)?;
276
277                e.encode_with(operator, ctx)?;
278                e.encode_with(vrf_keyhash, ctx)?;
279                e.encode_with(pledge, ctx)?;
280                e.encode_with(cost, ctx)?;
281                e.encode_with(margin, ctx)?;
282                e.encode_with(reward_account, ctx)?;
283                e.encode_with(pool_owners, ctx)?;
284                e.encode_with(relays, ctx)?;
285                e.encode_with(pool_metadata, ctx)?;
286            }
287            Certificate::PoolRetirement(a, b) => {
288                e.array(3)?;
289                e.u16(4)?;
290                e.encode_with(a, ctx)?;
291                e.encode_with(b, ctx)?;
292            }
293            // 5 and 6 removed in conway
294            Certificate::Reg(a, b) => {
295                e.array(3)?;
296                e.u16(7)?;
297                e.encode_with(a, ctx)?;
298                e.encode_with(b, ctx)?;
299            }
300            Certificate::UnReg(a, b) => {
301                e.array(3)?;
302                e.u16(8)?;
303                e.encode_with(a, ctx)?;
304                e.encode_with(b, ctx)?;
305            }
306            Certificate::VoteDeleg(a, b) => {
307                e.array(3)?;
308                e.u16(9)?;
309                e.encode_with(a, ctx)?;
310                e.encode_with(b, ctx)?;
311            }
312            Certificate::StakeVoteDeleg(a, b, c) => {
313                e.array(4)?;
314                e.u16(10)?;
315                e.encode_with(a, ctx)?;
316                e.encode_with(b, ctx)?;
317                e.encode_with(c, ctx)?;
318            }
319            Certificate::StakeRegDeleg(a, b, c) => {
320                e.array(4)?;
321                e.u16(11)?;
322                e.encode_with(a, ctx)?;
323                e.encode_with(b, ctx)?;
324                e.encode_with(c, ctx)?;
325            }
326            Certificate::VoteRegDeleg(a, b, c) => {
327                e.array(4)?;
328                e.u16(12)?;
329                e.encode_with(a, ctx)?;
330                e.encode_with(b, ctx)?;
331                e.encode_with(c, ctx)?;
332            }
333            Certificate::StakeVoteRegDeleg(a, b, c, d) => {
334                e.array(5)?;
335                e.u16(13)?;
336                e.encode_with(a, ctx)?;
337                e.encode_with(b, ctx)?;
338                e.encode_with(c, ctx)?;
339                e.encode_with(d, ctx)?;
340            }
341            Certificate::AuthCommitteeHot(a, b) => {
342                e.array(3)?;
343                e.u16(14)?;
344                e.encode_with(a, ctx)?;
345                e.encode_with(b, ctx)?;
346            }
347            Certificate::ResignCommitteeCold(a, b) => {
348                e.array(3)?;
349                e.u16(15)?;
350                e.encode_with(a, ctx)?;
351                e.encode_with(b, ctx)?;
352            }
353            Certificate::RegDRepCert(a, b, c) => {
354                e.array(4)?;
355                e.u16(16)?;
356                e.encode_with(a, ctx)?;
357                e.encode_with(b, ctx)?;
358                e.encode_with(c, ctx)?;
359            }
360            Certificate::UnRegDRepCert(a, b) => {
361                e.array(3)?;
362                e.u16(17)?;
363                e.encode_with(a, ctx)?;
364                e.encode_with(b, ctx)?;
365            }
366            Certificate::UpdateDRepCert(a, b) => {
367                e.array(3)?;
368                e.u16(18)?;
369                e.encode_with(a, ctx)?;
370                e.encode_with(b, ctx)?;
371            }
372        }
373
374        Ok(())
375    }
376}
377
378#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
379pub enum DRep {
380    Key(AddrKeyhash),
381    Script(ScriptHash),
382    Abstain,
383    NoConfidence,
384}
385
386impl<'b, C> minicbor::decode::Decode<'b, C> for DRep {
387    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
388        d.array()?;
389        let variant = d.u16()?;
390
391        match variant {
392            0 => Ok(DRep::Key(d.decode_with(ctx)?)),
393            1 => Ok(DRep::Script(d.decode_with(ctx)?)),
394            2 => Ok(DRep::Abstain),
395            3 => Ok(DRep::NoConfidence),
396            _ => Err(minicbor::decode::Error::message(
397                "invalid variant id for DRep",
398            )),
399        }
400    }
401}
402
403impl<C> minicbor::encode::Encode<C> for DRep {
404    fn encode<W: minicbor::encode::Write>(
405        &self,
406        e: &mut minicbor::Encoder<W>,
407        ctx: &mut C,
408    ) -> Result<(), minicbor::encode::Error<W::Error>> {
409        match self {
410            DRep::Key(h) => {
411                e.array(2)?;
412                e.encode_with(0, ctx)?;
413                e.encode_with(h, ctx)?;
414
415                Ok(())
416            }
417            DRep::Script(h) => {
418                e.array(2)?;
419                e.encode_with(1, ctx)?;
420                e.encode_with(h, ctx)?;
421
422                Ok(())
423            }
424            DRep::Abstain => {
425                e.array(1)?;
426                e.encode_with(2, ctx)?;
427
428                Ok(())
429            }
430            DRep::NoConfidence => {
431                e.array(1)?;
432                e.encode_with(3, ctx)?;
433
434                Ok(())
435            }
436        }
437    }
438}
439
440pub type DRepCredential = StakeCredential;
441
442pub type CommitteeColdCredential = StakeCredential;
443
444pub type CommitteeHotCredential = StakeCredential;
445
446#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
447#[cbor(index_only)]
448pub enum Language {
449    #[n(0)]
450    PlutusV1,
451
452    #[n(1)]
453    PlutusV2,
454
455    #[n(2)]
456    PlutusV3,
457}
458
459#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
460pub type CostMdls = CostModels;
461
462#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
463#[cbor(map)]
464pub struct CostModels {
465    #[n(0)]
466    pub plutus_v1: Option<CostModel>,
467
468    #[n(1)]
469    pub plutus_v2: Option<CostModel>,
470
471    #[n(2)]
472    pub plutus_v3: Option<CostModel>,
473}
474
475#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
476#[cbor(map)]
477pub struct ProtocolParamUpdate {
478    #[n(0)]
479    pub minfee_a: Option<u64>,
480    #[n(1)]
481    pub minfee_b: Option<u64>,
482    #[n(2)]
483    pub max_block_body_size: Option<u64>,
484    #[n(3)]
485    pub max_transaction_size: Option<u64>,
486    #[n(4)]
487    pub max_block_header_size: Option<u64>,
488    #[n(5)]
489    pub key_deposit: Option<Coin>,
490    #[n(6)]
491    pub pool_deposit: Option<Coin>,
492    #[n(7)]
493    pub maximum_epoch: Option<Epoch>,
494    #[n(8)]
495    pub desired_number_of_stake_pools: Option<u64>,
496    #[n(9)]
497    pub pool_pledge_influence: Option<RationalNumber>,
498    #[n(10)]
499    pub expansion_rate: Option<UnitInterval>,
500    #[n(11)]
501    pub treasury_growth_rate: Option<UnitInterval>,
502
503    #[n(16)]
504    pub min_pool_cost: Option<Coin>,
505    #[n(17)]
506    pub ada_per_utxo_byte: Option<Coin>,
507    #[n(18)]
508    pub cost_models_for_script_languages: Option<CostModels>,
509    #[n(19)]
510    pub execution_costs: Option<ExUnitPrices>,
511    #[n(20)]
512    pub max_tx_ex_units: Option<ExUnits>,
513    #[n(21)]
514    pub max_block_ex_units: Option<ExUnits>,
515    #[n(22)]
516    pub max_value_size: Option<u64>,
517    #[n(23)]
518    pub collateral_percentage: Option<u64>,
519    #[n(24)]
520    pub max_collateral_inputs: Option<u64>,
521
522    #[n(25)]
523    pub pool_voting_thresholds: Option<PoolVotingThresholds>,
524    #[n(26)]
525    pub drep_voting_thresholds: Option<DRepVotingThresholds>,
526    #[n(27)]
527    pub min_committee_size: Option<u64>,
528    #[n(28)]
529    pub committee_term_limit: Option<Epoch>,
530    #[n(29)]
531    pub governance_action_validity_period: Option<Epoch>,
532    #[n(30)]
533    pub governance_action_deposit: Option<Coin>,
534    #[n(31)]
535    pub drep_deposit: Option<Coin>,
536    #[n(32)]
537    pub drep_inactivity_period: Option<Epoch>,
538    #[n(33)]
539    pub minfee_refscript_cost_per_byte: Option<UnitInterval>,
540}
541
542#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
543pub struct Update {
544    #[n(0)]
545    pub proposed_protocol_parameter_updates: KeyValuePairs<Genesishash, ProtocolParamUpdate>,
546
547    #[n(1)]
548    pub epoch: Epoch,
549}
550
551#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
552pub struct PoolVotingThresholds {
553    pub motion_no_confidence: UnitInterval,
554    pub committee_normal: UnitInterval,
555    pub committee_no_confidence: UnitInterval,
556    pub hard_fork_initiation: UnitInterval,
557    pub security_voting_threshold: UnitInterval,
558}
559
560impl<'b, C> minicbor::Decode<'b, C> for PoolVotingThresholds {
561    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
562        d.array()?;
563
564        Ok(Self {
565            motion_no_confidence: d.decode_with(ctx)?,
566            committee_normal: d.decode_with(ctx)?,
567            committee_no_confidence: d.decode_with(ctx)?,
568            hard_fork_initiation: d.decode_with(ctx)?,
569            security_voting_threshold: d.decode_with(ctx)?,
570        })
571    }
572}
573
574impl<C> minicbor::Encode<C> for PoolVotingThresholds {
575    fn encode<W: minicbor::encode::Write>(
576        &self,
577        e: &mut minicbor::Encoder<W>,
578        ctx: &mut C,
579    ) -> Result<(), minicbor::encode::Error<W::Error>> {
580        e.array(5)?;
581
582        e.encode_with(&self.motion_no_confidence, ctx)?;
583        e.encode_with(&self.committee_normal, ctx)?;
584        e.encode_with(&self.committee_no_confidence, ctx)?;
585        e.encode_with(&self.hard_fork_initiation, ctx)?;
586        e.encode_with(&self.security_voting_threshold, ctx)?;
587
588        Ok(())
589    }
590}
591
592#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
593pub struct DRepVotingThresholds {
594    pub motion_no_confidence: UnitInterval,
595    pub committee_normal: UnitInterval,
596    pub committee_no_confidence: UnitInterval,
597    pub update_constitution: UnitInterval,
598    pub hard_fork_initiation: UnitInterval,
599    pub pp_network_group: UnitInterval,
600    pub pp_economic_group: UnitInterval,
601    pub pp_technical_group: UnitInterval,
602    pub pp_governance_group: UnitInterval,
603    pub treasury_withdrawal: UnitInterval,
604}
605
606impl<'b, C> minicbor::Decode<'b, C> for DRepVotingThresholds {
607    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
608        d.array()?;
609
610        Ok(Self {
611            motion_no_confidence: d.decode_with(ctx)?,
612            committee_normal: d.decode_with(ctx)?,
613            committee_no_confidence: d.decode_with(ctx)?,
614            update_constitution: d.decode_with(ctx)?,
615            hard_fork_initiation: d.decode_with(ctx)?,
616            pp_network_group: d.decode_with(ctx)?,
617            pp_economic_group: d.decode_with(ctx)?,
618            pp_technical_group: d.decode_with(ctx)?,
619            pp_governance_group: d.decode_with(ctx)?,
620            treasury_withdrawal: d.decode_with(ctx)?,
621        })
622    }
623}
624
625impl<C> minicbor::Encode<C> for DRepVotingThresholds {
626    fn encode<W: minicbor::encode::Write>(
627        &self,
628        e: &mut minicbor::Encoder<W>,
629        ctx: &mut C,
630    ) -> Result<(), minicbor::encode::Error<W::Error>> {
631        e.array(10)?;
632
633        e.encode_with(&self.motion_no_confidence, ctx)?;
634        e.encode_with(&self.committee_normal, ctx)?;
635        e.encode_with(&self.committee_no_confidence, ctx)?;
636        e.encode_with(&self.update_constitution, ctx)?;
637        e.encode_with(&self.hard_fork_initiation, ctx)?;
638        e.encode_with(&self.pp_network_group, ctx)?;
639        e.encode_with(&self.pp_economic_group, ctx)?;
640        e.encode_with(&self.pp_technical_group, ctx)?;
641        e.encode_with(&self.pp_governance_group, ctx)?;
642        e.encode_with(&self.treasury_withdrawal, ctx)?;
643
644        Ok(())
645    }
646}
647
648#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
649#[cbor(map)]
650pub struct PseudoTransactionBody<T1> {
651    #[n(0)]
652    pub inputs: Set<TransactionInput>,
653
654    #[n(1)]
655    pub outputs: Vec<T1>,
656
657    #[n(2)]
658    pub fee: Coin,
659
660    #[n(3)]
661    pub ttl: Option<u64>,
662
663    #[n(4)]
664    pub certificates: Option<NonEmptySet<Certificate>>,
665
666    #[n(5)]
667    pub withdrawals: Option<NonEmptyKeyValuePairs<RewardAccount, Coin>>,
668
669    #[n(7)]
670    pub auxiliary_data_hash: Option<Bytes>,
671
672    #[n(8)]
673    pub validity_interval_start: Option<u64>,
674
675    #[n(9)]
676    pub mint: Option<Multiasset<NonZeroInt>>,
677
678    #[n(11)]
679    pub script_data_hash: Option<Hash<32>>,
680
681    #[n(13)]
682    pub collateral: Option<NonEmptySet<TransactionInput>>,
683
684    #[n(14)]
685    pub required_signers: Option<RequiredSigners>,
686
687    #[n(15)]
688    pub network_id: Option<NetworkId>,
689
690    #[n(16)]
691    pub collateral_return: Option<T1>,
692
693    #[n(17)]
694    pub total_collateral: Option<Coin>,
695
696    #[n(18)]
697    pub reference_inputs: Option<NonEmptySet<TransactionInput>>,
698
699    // -- NEW IN CONWAY
700    #[n(19)]
701    pub voting_procedures: Option<VotingProcedures>,
702
703    #[n(20)]
704    pub proposal_procedures: Option<NonEmptySet<ProposalProcedure>>,
705
706    #[n(21)]
707    pub treasury_value: Option<Coin>,
708
709    #[n(22)]
710    pub donation: Option<PositiveCoin>,
711}
712
713pub type TransactionBody = PseudoTransactionBody<TransactionOutput>;
714
715pub type MintedTransactionBody<'a> = PseudoTransactionBody<MintedTransactionOutput<'a>>;
716
717impl<'a> From<MintedTransactionBody<'a>> for TransactionBody {
718    fn from(value: MintedTransactionBody<'a>) -> Self {
719        Self {
720            inputs: value.inputs,
721            outputs: value.outputs.into_iter().map(|x| x.into()).collect(),
722            fee: value.fee,
723            ttl: value.ttl,
724            certificates: value.certificates,
725            withdrawals: value.withdrawals,
726            auxiliary_data_hash: value.auxiliary_data_hash,
727            validity_interval_start: value.validity_interval_start,
728            mint: value.mint,
729            script_data_hash: value.script_data_hash,
730            collateral: value.collateral,
731            required_signers: value.required_signers,
732            network_id: value.network_id,
733            collateral_return: value.collateral_return.map(|x| x.into()),
734            total_collateral: value.total_collateral,
735            reference_inputs: value.reference_inputs,
736            voting_procedures: value.voting_procedures,
737            proposal_procedures: value.proposal_procedures,
738            treasury_value: value.treasury_value,
739            donation: value.donation,
740        }
741    }
742}
743
744#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
745pub enum Vote {
746    No,
747    Yes,
748    Abstain,
749}
750
751impl<'b, C> minicbor::Decode<'b, C> for Vote {
752    fn decode(
753        d: &mut minicbor::Decoder<'b>,
754        _ctx: &mut C,
755    ) -> Result<Self, minicbor::decode::Error> {
756        match d.u8()? {
757            0 => Ok(Self::No),
758            1 => Ok(Self::Yes),
759            2 => Ok(Self::Abstain),
760            _ => Err(minicbor::decode::Error::message(
761                "invalid number for Vote kind",
762            )),
763        }
764    }
765}
766
767impl<C> minicbor::Encode<C> for Vote {
768    fn encode<W: minicbor::encode::Write>(
769        &self,
770        e: &mut minicbor::Encoder<W>,
771        _ctx: &mut C,
772    ) -> Result<(), minicbor::encode::Error<W::Error>> {
773        match &self {
774            Self::No => e.u8(0)?,
775            Self::Yes => e.u8(1)?,
776            Self::Abstain => e.u8(2)?,
777        };
778
779        Ok(())
780    }
781}
782
783pub type VotingProcedures =
784    NonEmptyKeyValuePairs<Voter, NonEmptyKeyValuePairs<GovActionId, VotingProcedure>>;
785
786#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
787pub struct VotingProcedure {
788    pub vote: Vote,
789    pub anchor: Nullable<Anchor>,
790}
791
792impl<'b, C> minicbor::Decode<'b, C> for VotingProcedure {
793    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
794        d.array()?;
795
796        Ok(Self {
797            vote: d.decode_with(ctx)?,
798            anchor: d.decode_with(ctx)?,
799        })
800    }
801}
802
803impl<C> minicbor::Encode<C> for VotingProcedure {
804    fn encode<W: minicbor::encode::Write>(
805        &self,
806        e: &mut minicbor::Encoder<W>,
807        ctx: &mut C,
808    ) -> Result<(), minicbor::encode::Error<W::Error>> {
809        e.array(2)?;
810
811        e.encode_with(&self.vote, ctx)?;
812        e.encode_with(&self.anchor, ctx)?;
813
814        Ok(())
815    }
816}
817
818#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
819pub struct ProposalProcedure {
820    pub deposit: Coin,
821    pub reward_account: RewardAccount,
822    pub gov_action: GovAction,
823    pub anchor: Anchor,
824}
825
826impl<'b, C> minicbor::Decode<'b, C> for ProposalProcedure {
827    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
828        d.array()?;
829
830        Ok(Self {
831            deposit: d.decode_with(ctx)?,
832            reward_account: d.decode_with(ctx)?,
833            gov_action: d.decode_with(ctx)?,
834            anchor: d.decode_with(ctx)?,
835        })
836    }
837}
838
839impl<C> minicbor::Encode<C> for ProposalProcedure {
840    fn encode<W: minicbor::encode::Write>(
841        &self,
842        e: &mut minicbor::Encoder<W>,
843        ctx: &mut C,
844    ) -> Result<(), minicbor::encode::Error<W::Error>> {
845        e.array(4)?;
846
847        e.encode_with(self.deposit, ctx)?;
848        e.encode_with(&self.reward_account, ctx)?;
849        e.encode_with(&self.gov_action, ctx)?;
850        e.encode_with(&self.anchor, ctx)?;
851
852        Ok(())
853    }
854}
855
856#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
857pub enum GovAction {
858    ParameterChange(
859        Nullable<GovActionId>,
860        Box<ProtocolParamUpdate>,
861        Nullable<ScriptHash>,
862    ),
863    HardForkInitiation(Nullable<GovActionId>, ProtocolVersion),
864    TreasuryWithdrawals(KeyValuePairs<RewardAccount, Coin>, Nullable<ScriptHash>),
865    NoConfidence(Nullable<GovActionId>),
866    UpdateCommittee(
867        Nullable<GovActionId>,
868        Set<CommitteeColdCredential>,
869        KeyValuePairs<CommitteeColdCredential, Epoch>,
870        UnitInterval,
871    ),
872    NewConstitution(Nullable<GovActionId>, Constitution),
873    Information,
874}
875
876impl<'b, C> minicbor::decode::Decode<'b, C> for GovAction {
877    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
878        d.array()?;
879        let variant = d.u16()?;
880
881        match variant {
882            0 => {
883                let a = d.decode_with(ctx)?;
884                let b = d.decode_with(ctx)?;
885                let c = d.decode_with(ctx)?;
886                Ok(GovAction::ParameterChange(a, b, c))
887            }
888            1 => {
889                let a = d.decode_with(ctx)?;
890                let b = d.decode_with(ctx)?;
891                Ok(GovAction::HardForkInitiation(a, b))
892            }
893            2 => {
894                let a = d.decode_with(ctx)?;
895                let b = d.decode_with(ctx)?;
896                Ok(GovAction::TreasuryWithdrawals(a, b))
897            }
898            3 => {
899                let a = d.decode_with(ctx)?;
900                Ok(GovAction::NoConfidence(a))
901            }
902            4 => {
903                let a = d.decode_with(ctx)?;
904                let b = d.decode_with(ctx)?;
905                let c = d.decode_with(ctx)?;
906                let d = d.decode_with(ctx)?;
907                Ok(GovAction::UpdateCommittee(a, b, c, d))
908            }
909            5 => {
910                let a = d.decode_with(ctx)?;
911                let b = d.decode_with(ctx)?;
912                Ok(GovAction::NewConstitution(a, b))
913            }
914            6 => Ok(GovAction::Information),
915            _ => Err(minicbor::decode::Error::message(
916                "unknown variant id for certificate",
917            )),
918        }
919    }
920}
921
922impl<C> minicbor::encode::Encode<C> for GovAction {
923    fn encode<W: minicbor::encode::Write>(
924        &self,
925        e: &mut minicbor::Encoder<W>,
926        ctx: &mut C,
927    ) -> Result<(), minicbor::encode::Error<W::Error>> {
928        match self {
929            GovAction::ParameterChange(a, b, c) => {
930                e.array(4)?;
931                e.u16(0)?;
932                e.encode_with(a, ctx)?;
933                e.encode_with(b, ctx)?;
934                e.encode_with(c, ctx)?;
935            }
936            GovAction::HardForkInitiation(a, b) => {
937                e.array(3)?;
938                e.u16(1)?;
939                e.encode_with(a, ctx)?;
940                e.encode_with(b, ctx)?;
941            }
942            GovAction::TreasuryWithdrawals(a, b) => {
943                e.array(3)?;
944                e.u16(2)?;
945                e.encode_with(a, ctx)?;
946                e.encode_with(b, ctx)?;
947            }
948            GovAction::NoConfidence(a) => {
949                e.array(2)?;
950                e.u16(3)?;
951                e.encode_with(a, ctx)?;
952            }
953            GovAction::UpdateCommittee(a, b, c, d) => {
954                e.array(5)?;
955                e.u16(4)?;
956                e.encode_with(a, ctx)?;
957                e.encode_with(b, ctx)?;
958                e.encode_with(c, ctx)?;
959                e.encode_with(d, ctx)?;
960            }
961            GovAction::NewConstitution(a, b) => {
962                e.array(3)?;
963                e.u16(5)?;
964                e.encode_with(a, ctx)?;
965                e.encode_with(b, ctx)?;
966            }
967            // TODO: CDDL says just "6", not group/array "(6)"?
968            GovAction::Information => {
969                e.array(1)?;
970                e.u16(6)?;
971            }
972        }
973
974        Ok(())
975    }
976}
977
978#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
979pub struct Constitution {
980    pub anchor: Anchor,
981    pub guardrail_script: Nullable<ScriptHash>,
982}
983
984impl<'b, C> minicbor::Decode<'b, C> for Constitution {
985    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
986        d.array()?;
987
988        Ok(Self {
989            anchor: d.decode_with(ctx)?,
990            guardrail_script: d.decode_with(ctx)?,
991        })
992    }
993}
994
995impl<C> minicbor::Encode<C> for Constitution {
996    fn encode<W: minicbor::encode::Write>(
997        &self,
998        e: &mut minicbor::Encoder<W>,
999        ctx: &mut C,
1000    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1001        e.array(2)?;
1002
1003        e.encode_with(&self.anchor, ctx)?;
1004        e.encode_with(&self.guardrail_script, ctx)?;
1005
1006        Ok(())
1007    }
1008}
1009
1010#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
1011pub enum Voter {
1012    ConstitutionalCommitteeScript(ScriptHash),
1013    ConstitutionalCommitteeKey(AddrKeyhash),
1014    DRepScript(ScriptHash),
1015    DRepKey(AddrKeyhash),
1016    StakePoolKey(AddrKeyhash),
1017}
1018
1019impl<'b, C> minicbor::decode::Decode<'b, C> for Voter {
1020    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1021        d.array()?;
1022        let variant = d.u16()?;
1023
1024        match variant {
1025            0 => Ok(Voter::ConstitutionalCommitteeKey(d.decode_with(ctx)?)),
1026            1 => Ok(Voter::ConstitutionalCommitteeScript(d.decode_with(ctx)?)),
1027            2 => Ok(Voter::DRepKey(d.decode_with(ctx)?)),
1028            3 => Ok(Voter::DRepScript(d.decode_with(ctx)?)),
1029            4 => Ok(Voter::StakePoolKey(d.decode_with(ctx)?)),
1030            _ => Err(minicbor::decode::Error::message(
1031                "invalid variant id for DRep",
1032            )),
1033        }
1034    }
1035}
1036
1037impl<C> minicbor::encode::Encode<C> for Voter {
1038    fn encode<W: minicbor::encode::Write>(
1039        &self,
1040        e: &mut minicbor::Encoder<W>,
1041        ctx: &mut C,
1042    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1043        e.array(2)?;
1044
1045        match self {
1046            Voter::ConstitutionalCommitteeKey(h) => {
1047                e.encode_with(0, ctx)?;
1048                e.encode_with(h, ctx)?;
1049
1050                Ok(())
1051            }
1052            Voter::ConstitutionalCommitteeScript(h) => {
1053                e.encode_with(1, ctx)?;
1054                e.encode_with(h, ctx)?;
1055
1056                Ok(())
1057            }
1058            Voter::DRepKey(h) => {
1059                e.encode_with(2, ctx)?;
1060                e.encode_with(h, ctx)?;
1061
1062                Ok(())
1063            }
1064            Voter::DRepScript(h) => {
1065                e.encode_with(3, ctx)?;
1066                e.encode_with(h, ctx)?;
1067
1068                Ok(())
1069            }
1070            Voter::StakePoolKey(h) => {
1071                e.encode_with(4, ctx)?;
1072                e.encode_with(h, ctx)?;
1073
1074                Ok(())
1075            }
1076        }
1077    }
1078}
1079
1080#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
1081pub struct Anchor {
1082    pub url: String,
1083    pub content_hash: Hash<32>,
1084}
1085
1086impl<'b, C> minicbor::Decode<'b, C> for Anchor {
1087    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1088        d.array()?;
1089
1090        Ok(Self {
1091            url: d.decode_with(ctx)?,
1092            content_hash: d.decode_with(ctx)?,
1093        })
1094    }
1095}
1096
1097impl<C> minicbor::Encode<C> for Anchor {
1098    fn encode<W: minicbor::encode::Write>(
1099        &self,
1100        e: &mut minicbor::Encoder<W>,
1101        ctx: &mut C,
1102    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1103        e.array(2)?;
1104
1105        e.encode_with(&self.url, ctx)?;
1106        e.encode_with(self.content_hash, ctx)?;
1107
1108        Ok(())
1109    }
1110}
1111
1112#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
1113pub struct GovActionId {
1114    pub transaction_id: Hash<32>,
1115    pub action_index: u32,
1116}
1117
1118impl<'b, C> minicbor::Decode<'b, C> for GovActionId {
1119    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1120        d.array()?;
1121
1122        Ok(Self {
1123            transaction_id: d.decode_with(ctx)?,
1124            action_index: d.decode_with(ctx)?,
1125        })
1126    }
1127}
1128
1129impl<C> minicbor::Encode<C> for GovActionId {
1130    fn encode<W: minicbor::encode::Write>(
1131        &self,
1132        e: &mut minicbor::Encoder<W>,
1133        ctx: &mut C,
1134    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1135        e.array(2)?;
1136
1137        e.encode_with(self.transaction_id, ctx)?;
1138        e.encode_with(self.action_index, ctx)?;
1139
1140        Ok(())
1141    }
1142}
1143
1144#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
1145pub enum PseudoTransactionOutput<T> {
1146    Legacy(LegacyTransactionOutput),
1147    PostAlonzo(T),
1148}
1149
1150impl<'b, C, T> minicbor::Decode<'b, C> for PseudoTransactionOutput<T>
1151where
1152    T: minicbor::Decode<'b, C>,
1153{
1154    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1155        match d.datatype()? {
1156            minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
1157                Ok(PseudoTransactionOutput::Legacy(d.decode_with(ctx)?))
1158            }
1159            minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
1160                Ok(PseudoTransactionOutput::PostAlonzo(d.decode_with(ctx)?))
1161            }
1162            _ => Err(minicbor::decode::Error::message(
1163                "invalid type for transaction output struct",
1164            )),
1165        }
1166    }
1167}
1168
1169impl<C, T> minicbor::Encode<C> for PseudoTransactionOutput<T>
1170where
1171    T: minicbor::Encode<C>,
1172{
1173    fn encode<W: minicbor::encode::Write>(
1174        &self,
1175        e: &mut minicbor::Encoder<W>,
1176        ctx: &mut C,
1177    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1178        match self {
1179            PseudoTransactionOutput::Legacy(x) => x.encode(e, ctx),
1180            PseudoTransactionOutput::PostAlonzo(x) => x.encode(e, ctx),
1181        }
1182    }
1183}
1184
1185pub type PostAlonzoTransactionOutput =
1186    crate::babbage::PseudoPostAlonzoTransactionOutput<Value, DatumOption, ScriptRef>;
1187
1188pub type TransactionOutput = PseudoTransactionOutput<PostAlonzoTransactionOutput>;
1189
1190pub type MintedTransactionOutput<'b> =
1191    PseudoTransactionOutput<MintedPostAlonzoTransactionOutput<'b>>;
1192
1193impl<'b> From<MintedTransactionOutput<'b>> for TransactionOutput {
1194    fn from(value: MintedTransactionOutput<'b>) -> Self {
1195        match value {
1196            PseudoTransactionOutput::Legacy(x) => Self::Legacy(x),
1197            PseudoTransactionOutput::PostAlonzo(x) => Self::PostAlonzo(x.into()),
1198        }
1199    }
1200}
1201
1202pub type MintedPostAlonzoTransactionOutput<'b> = crate::babbage::PseudoPostAlonzoTransactionOutput<
1203    Value,
1204    MintedDatumOption<'b>,
1205    MintedScriptRef<'b>,
1206>;
1207
1208impl<'b> From<MintedPostAlonzoTransactionOutput<'b>> for PostAlonzoTransactionOutput {
1209    fn from(value: MintedPostAlonzoTransactionOutput<'b>) -> Self {
1210        Self {
1211            address: value.address,
1212            value: value.value,
1213            datum_option: value.datum_option.map(|x| x.into()),
1214            script_ref: value.script_ref.map(|x| CborWrap(x.unwrap().into())),
1215        }
1216    }
1217}
1218
1219pub use crate::alonzo::VKeyWitness;
1220
1221pub use crate::alonzo::NativeScript;
1222
1223#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1224pub struct ExUnitPrices {
1225    #[n(0)]
1226    pub mem_price: RationalNumber,
1227
1228    #[n(1)]
1229    pub step_price: RationalNumber,
1230}
1231
1232#[derive(
1233    Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy,
1234)]
1235#[cbor(index_only)]
1236pub enum RedeemerTag {
1237    #[n(0)]
1238    Spend,
1239    #[n(1)]
1240    Mint,
1241    #[n(2)]
1242    Cert,
1243    #[n(3)]
1244    Reward,
1245    #[n(4)]
1246    Vote,
1247    #[n(5)]
1248    Propose,
1249}
1250
1251#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1252pub struct Redeemer {
1253    #[n(0)]
1254    pub tag: RedeemerTag,
1255
1256    #[n(1)]
1257    pub index: u32,
1258
1259    #[n(2)]
1260    pub data: PlutusData,
1261
1262    #[n(3)]
1263    pub ex_units: ExUnits,
1264}
1265
1266#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
1267pub struct RedeemersKey {
1268    #[n(0)]
1269    pub tag: RedeemerTag,
1270    #[n(1)]
1271    pub index: u32,
1272}
1273
1274#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1275pub struct RedeemersValue {
1276    #[n(0)]
1277    pub data: PlutusData,
1278    #[n(1)]
1279    pub ex_units: ExUnits,
1280}
1281
1282#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
1283pub enum Redeemers {
1284    List(MaybeIndefArray<Redeemer>),
1285    Map(NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>),
1286}
1287
1288impl From<NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>> for Redeemers {
1289    fn from(value: NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>) -> Self {
1290        Redeemers::Map(value)
1291    }
1292}
1293
1294impl<'b, C> minicbor::Decode<'b, C> for Redeemers {
1295    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1296        match d.datatype()? {
1297            minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
1298                Ok(Self::List(d.decode_with(ctx)?))
1299            }
1300            minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
1301                Ok(Self::Map(d.decode_with(ctx)?))
1302            }
1303            _ => Err(minicbor::decode::Error::message(
1304                "invalid type for redeemers struct",
1305            )),
1306        }
1307    }
1308}
1309
1310impl<C> minicbor::Encode<C> for Redeemers {
1311    fn encode<W: minicbor::encode::Write>(
1312        &self,
1313        e: &mut minicbor::Encoder<W>,
1314        ctx: &mut C,
1315    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1316        match self {
1317            Self::List(x) => e.encode_with(x, ctx)?,
1318            Self::Map(x) => e.encode_with(x, ctx)?,
1319        };
1320
1321        Ok(())
1322    }
1323}
1324
1325pub use crate::alonzo::BootstrapWitness;
1326
1327#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1328#[cbor(map)]
1329pub struct WitnessSet {
1330    #[n(0)]
1331    pub vkeywitness: Option<NonEmptySet<VKeyWitness>>,
1332
1333    #[n(1)]
1334    pub native_script: Option<NonEmptySet<NativeScript>>,
1335
1336    #[n(2)]
1337    pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
1338
1339    #[n(3)]
1340    pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
1341
1342    #[n(4)]
1343    pub plutus_data: Option<NonEmptySet<PlutusData>>,
1344
1345    #[n(5)]
1346    pub redeemer: Option<Redeemers>,
1347
1348    #[n(6)]
1349    pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
1350
1351    #[n(7)]
1352    pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
1353}
1354
1355#[derive(Encode, Decode, Debug, PartialEq, Clone)]
1356#[cbor(map)]
1357pub struct MintedWitnessSet<'b> {
1358    #[n(0)]
1359    pub vkeywitness: Option<NonEmptySet<VKeyWitness>>,
1360
1361    #[n(1)]
1362    pub native_script: Option<NonEmptySet<KeepRaw<'b, NativeScript>>>,
1363
1364    #[n(2)]
1365    pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
1366
1367    #[n(3)]
1368    pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
1369
1370    #[b(4)]
1371    pub plutus_data: Option<NonEmptySet<KeepRaw<'b, PlutusData>>>,
1372
1373    #[n(5)]
1374    pub redeemer: Option<KeepRaw<'b, Redeemers>>,
1375
1376    #[n(6)]
1377    pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
1378
1379    #[n(7)]
1380    pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
1381}
1382
1383impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
1384    fn from(x: MintedWitnessSet<'b>) -> Self {
1385        WitnessSet {
1386            vkeywitness: x.vkeywitness,
1387            native_script: x.native_script.map(Into::into),
1388            bootstrap_witness: x.bootstrap_witness,
1389            plutus_v1_script: x.plutus_v1_script,
1390            plutus_data: x.plutus_data.map(Into::into),
1391            redeemer: x.redeemer.map(|x| x.unwrap()),
1392            plutus_v2_script: x.plutus_v2_script,
1393            plutus_v3_script: x.plutus_v3_script,
1394        }
1395    }
1396}
1397
1398#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
1399#[cbor(map)]
1400pub struct PostAlonzoAuxiliaryData {
1401    #[n(0)]
1402    pub metadata: Option<Metadata>,
1403
1404    #[n(1)]
1405    pub native_scripts: Option<Vec<NativeScript>>,
1406
1407    #[n(2)]
1408    pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
1409
1410    #[n(3)]
1411    pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
1412
1413    #[n(4)]
1414    pub plutus_v3_scripts: Option<Vec<PlutusScript<3>>>,
1415}
1416
1417pub use crate::babbage::DatumHash;
1418
1419pub use crate::babbage::PseudoDatumOption;
1420
1421pub use crate::babbage::DatumOption;
1422
1423pub use crate::babbage::MintedDatumOption;
1424
1425#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
1426pub type PlutusV1Script = PlutusScript<1>;
1427
1428#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
1429pub type PlutusV2Script = PlutusScript<2>;
1430
1431#[deprecated(since = "0.31.0", note = "use `PlutusScript<3>` instead")]
1432pub type PlutusV3Script = PlutusScript<3>;
1433
1434// script = [ 0, native_script // 1, plutus_v1_script // 2, plutus_v2_script ]
1435#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
1436pub enum PseudoScript<T1> {
1437    NativeScript(T1),
1438    PlutusV1Script(PlutusScript<1>),
1439    PlutusV2Script(PlutusScript<2>),
1440    PlutusV3Script(PlutusScript<3>),
1441}
1442
1443// script_ref = #6.24(bytes .cbor script)
1444pub type ScriptRef = PseudoScript<NativeScript>;
1445
1446pub type MintedScriptRef<'b> = PseudoScript<KeepRaw<'b, NativeScript>>;
1447
1448impl<'b> From<MintedScriptRef<'b>> for ScriptRef {
1449    fn from(value: MintedScriptRef<'b>) -> Self {
1450        match value {
1451            PseudoScript::NativeScript(x) => Self::NativeScript(x.unwrap()),
1452            PseudoScript::PlutusV1Script(x) => Self::PlutusV1Script(x),
1453            PseudoScript::PlutusV2Script(x) => Self::PlutusV2Script(x),
1454            PseudoScript::PlutusV3Script(x) => Self::PlutusV3Script(x),
1455        }
1456    }
1457}
1458
1459// TODO: Remove in favour of multierascriptref
1460impl<'b> From<babbage::MintedScriptRef<'b>> for MintedScriptRef<'b> {
1461    fn from(value: babbage::MintedScriptRef<'b>) -> Self {
1462        match value {
1463            babbage::MintedScriptRef::NativeScript(x) => Self::NativeScript(x),
1464            babbage::MintedScriptRef::PlutusV1Script(x) => Self::PlutusV1Script(x),
1465            babbage::MintedScriptRef::PlutusV2Script(x) => Self::PlutusV2Script(x),
1466        }
1467    }
1468}
1469
1470impl<'b, C, T> minicbor::Decode<'b, C> for PseudoScript<T>
1471where
1472    T: minicbor::Decode<'b, ()>,
1473{
1474    fn decode(
1475        d: &mut minicbor::Decoder<'b>,
1476        _ctx: &mut C,
1477    ) -> Result<Self, minicbor::decode::Error> {
1478        d.array()?;
1479
1480        match d.u8()? {
1481            0 => Ok(Self::NativeScript(d.decode()?)),
1482            1 => Ok(Self::PlutusV1Script(d.decode()?)),
1483            2 => Ok(Self::PlutusV2Script(d.decode()?)),
1484            3 => Ok(Self::PlutusV3Script(d.decode()?)),
1485            x => Err(minicbor::decode::Error::message(format!(
1486                "invalid variant for script enum: {}",
1487                x
1488            ))),
1489        }
1490    }
1491}
1492
1493impl<C, T> minicbor::Encode<C> for PseudoScript<T>
1494where
1495    T: minicbor::Encode<C>,
1496{
1497    fn encode<W: minicbor::encode::Write>(
1498        &self,
1499        e: &mut minicbor::Encoder<W>,
1500        ctx: &mut C,
1501    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1502        match self {
1503            Self::NativeScript(x) => e.encode_with((0, x), ctx)?,
1504            Self::PlutusV1Script(x) => e.encode_with((1, x), ctx)?,
1505            Self::PlutusV2Script(x) => e.encode_with((2, x), ctx)?,
1506            Self::PlutusV3Script(x) => e.encode_with((3, x), ctx)?,
1507        };
1508
1509        Ok(())
1510    }
1511}
1512
1513pub use crate::alonzo::AuxiliaryData;
1514
1515use crate::babbage::MintedHeader;
1516
1517#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
1518pub struct PseudoBlock<T1, T2, T3, T4>
1519where
1520    T4: std::clone::Clone,
1521{
1522    #[n(0)]
1523    pub header: T1,
1524
1525    #[b(1)]
1526    pub transaction_bodies: MaybeIndefArray<T2>,
1527
1528    #[n(2)]
1529    pub transaction_witness_sets: MaybeIndefArray<T3>,
1530
1531    #[n(3)]
1532    pub auxiliary_data_set: KeyValuePairs<TransactionIndex, T4>,
1533
1534    #[n(4)]
1535    pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
1536}
1537
1538pub type Block = PseudoBlock<Header, TransactionBody, WitnessSet, AuxiliaryData>;
1539
1540/// A memory representation of an already minted block
1541///
1542/// This structure is analogous to [Block], but it allows to retrieve the
1543/// original CBOR bytes for each structure that might require hashing. In this
1544/// way, we make sure that the resulting hash matches what exists on-chain.
1545pub type MintedBlock<'b> = PseudoBlock<
1546    KeepRaw<'b, MintedHeader<'b>>,
1547    KeepRaw<'b, MintedTransactionBody<'b>>,
1548    KeepRaw<'b, MintedWitnessSet<'b>>,
1549    KeepRaw<'b, AuxiliaryData>,
1550>;
1551
1552impl<'b> From<MintedBlock<'b>> for Block {
1553    fn from(x: MintedBlock<'b>) -> Self {
1554        Block {
1555            header: x.header.unwrap().into(),
1556            transaction_bodies: MaybeIndefArray::Def(
1557                x.transaction_bodies
1558                    .iter()
1559                    .cloned()
1560                    .map(|x| x.unwrap())
1561                    .map(TransactionBody::from)
1562                    .collect(),
1563            ),
1564            transaction_witness_sets: MaybeIndefArray::Def(
1565                x.transaction_witness_sets
1566                    .iter()
1567                    .cloned()
1568                    .map(|x| x.unwrap())
1569                    .map(WitnessSet::from)
1570                    .collect(),
1571            ),
1572            auxiliary_data_set: x
1573                .auxiliary_data_set
1574                .to_vec()
1575                .into_iter()
1576                .map(|(k, v)| (k, v.unwrap()))
1577                .collect::<Vec<_>>()
1578                .into(),
1579            invalid_transactions: x.invalid_transactions,
1580        }
1581    }
1582}
1583
1584#[derive(Clone, Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq)]
1585pub struct PseudoTx<T1, T2, T3>
1586where
1587    T1: std::clone::Clone,
1588    T2: std::clone::Clone,
1589    T3: std::clone::Clone,
1590{
1591    #[n(0)]
1592    pub transaction_body: T1,
1593
1594    #[n(1)]
1595    pub transaction_witness_set: T2,
1596
1597    #[n(2)]
1598    pub success: bool,
1599
1600    #[n(3)]
1601    pub auxiliary_data: Nullable<T3>,
1602}
1603
1604pub type Tx = PseudoTx<TransactionBody, WitnessSet, AuxiliaryData>;
1605
1606pub type MintedTx<'b> = PseudoTx<
1607    KeepRaw<'b, MintedTransactionBody<'b>>,
1608    KeepRaw<'b, MintedWitnessSet<'b>>,
1609    KeepRaw<'b, AuxiliaryData>,
1610>;
1611
1612impl<'b> From<MintedTx<'b>> for Tx {
1613    fn from(x: MintedTx<'b>) -> Self {
1614        Tx {
1615            transaction_body: x.transaction_body.unwrap().into(),
1616            transaction_witness_set: x.transaction_witness_set.unwrap().into(),
1617            success: x.success,
1618            auxiliary_data: x.auxiliary_data.map(|x| x.unwrap()),
1619        }
1620    }
1621}
1622
1623#[cfg(test)]
1624mod tests {
1625    use pallas_codec::minicbor;
1626
1627    use super::MintedBlock;
1628
1629    type BlockWrapper<'b> = (u16, MintedBlock<'b>);
1630
1631    #[cfg(test)]
1632    mod tests_voter {
1633        use super::super::Voter;
1634        use crate::Hash;
1635        use std::cmp::Ordering;
1636        use test_case::test_case;
1637
1638        fn fake_hash(prefix: &str) -> Hash<28> {
1639            let null_hash: [u8; 28] = [
1640                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1641            ];
1642            Hash::from(&[prefix.as_bytes(), &null_hash].concat()[0..28])
1643        }
1644
1645        fn cc_script(prefix: &str) -> Voter {
1646            Voter::ConstitutionalCommitteeScript(fake_hash(prefix))
1647        }
1648
1649        fn cc_key(prefix: &str) -> Voter {
1650            Voter::ConstitutionalCommitteeKey(fake_hash(prefix))
1651        }
1652
1653        fn drep_script(prefix: &str) -> Voter {
1654            Voter::DRepScript(fake_hash(prefix))
1655        }
1656
1657        fn drep_key(prefix: &str) -> Voter {
1658            Voter::DRepKey(fake_hash(prefix))
1659        }
1660
1661        fn spo(prefix: &str) -> Voter {
1662            Voter::StakePoolKey(fake_hash(prefix))
1663        }
1664
1665        #[test_case(cc_script("alice"), cc_script("alice") => Ordering::Equal)]
1666        #[test_case(cc_script("alice"), cc_key("alice") => Ordering::Less)]
1667        #[test_case(cc_script("alice"), drep_script("alice") => Ordering::Less)]
1668        #[test_case(cc_script("alice"), drep_key("alice") => Ordering::Less)]
1669        #[test_case(cc_script("alice"), spo("alice") => Ordering::Less)]
1670        #[test_case(cc_script("bob"), cc_script("alice") => Ordering::Greater)]
1671        #[test_case(drep_script("alice"), cc_script("alice") => Ordering::Greater)]
1672        #[test_case(drep_script("alice"), cc_key("alice") => Ordering::Greater)]
1673        #[test_case(drep_script("alice"), drep_script("alice") => Ordering::Equal)]
1674        #[test_case(drep_script("alice"), drep_key("alice") => Ordering::Less)]
1675        #[test_case(drep_script("alice"), spo("alice") => Ordering::Less)]
1676        #[test_case(drep_script("bob"), drep_script("alice") => Ordering::Greater)]
1677        fn voter_ordering(left: Voter, right: Voter) -> Ordering {
1678            left.cmp(&right)
1679        }
1680    }
1681
1682    #[test]
1683    fn block_isomorphic_decoding_encoding() {
1684        let test_blocks = [
1685            include_str!("../../../test_data/conway1.block"),
1686            include_str!("../../../test_data/conway2.block"),
1687            // interesting block with extreme values
1688            include_str!("../../../test_data/conway3.block"),
1689            // interesting block with extreme values
1690            include_str!("../../../test_data/conway4.block"),
1691        ];
1692
1693        for (idx, block_str) in test_blocks.iter().enumerate() {
1694            println!("decoding test block {}", idx + 1);
1695            let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
1696
1697            let block: BlockWrapper = minicbor::decode(&bytes)
1698                .unwrap_or_else(|e| panic!("error decoding cbor for file {idx}: {e:?}"));
1699
1700            let bytes2 = minicbor::to_vec(block)
1701                .unwrap_or_else(|e| panic!("error encoding block cbor for file {idx}: {e:?}"));
1702
1703            assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
1704        }
1705    }
1706
1707    // #[test]
1708    // fn fragments_decoding() {
1709    //     // peculiar array of outputs used in an hydra transaction
1710    //     let bytes = hex::decode(hex).unwrap();
1711    //     let outputs =
1712    // Vec::<TransactionOutput>::decode_fragment(&bytes).unwrap();
1713    //
1714    //     dbg!(outputs);
1715    //
1716    //     // add any loose fragment tests here
1717    // }
1718}