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, Clone)]
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    ConstitutionalCommitteeKey(AddrKeyhash),
1013    ConstitutionalCommitteeScript(ScriptHash),
1014    DRepKey(AddrKeyhash),
1015    DRepScript(ScriptHash),
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)]
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(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
1233#[cbor(index_only)]
1234pub enum RedeemerTag {
1235    #[n(0)]
1236    Spend,
1237    #[n(1)]
1238    Mint,
1239    #[n(2)]
1240    Cert,
1241    #[n(3)]
1242    Reward,
1243    #[n(4)]
1244    Vote,
1245    #[n(5)]
1246    Propose,
1247}
1248
1249#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1250pub struct Redeemer {
1251    #[n(0)]
1252    pub tag: RedeemerTag,
1253
1254    #[n(1)]
1255    pub index: u32,
1256
1257    #[n(2)]
1258    pub data: PlutusData,
1259
1260    #[n(3)]
1261    pub ex_units: ExUnits,
1262}
1263
1264#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1265pub struct RedeemersKey {
1266    #[n(0)]
1267    pub tag: RedeemerTag,
1268    #[n(1)]
1269    pub index: u32,
1270}
1271
1272#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
1273pub struct RedeemersValue {
1274    #[n(0)]
1275    pub data: PlutusData,
1276    #[n(1)]
1277    pub ex_units: ExUnits,
1278}
1279
1280#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
1281pub enum Redeemers {
1282    List(MaybeIndefArray<Redeemer>),
1283    Map(NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>),
1284}
1285
1286impl From<NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>> for Redeemers {
1287    fn from(value: NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>) -> Self {
1288        Redeemers::Map(value)
1289    }
1290}
1291
1292impl<'b, C> minicbor::Decode<'b, C> for Redeemers {
1293    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
1294        match d.datatype()? {
1295            minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
1296                Ok(Self::List(d.decode_with(ctx)?))
1297            }
1298            minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
1299                Ok(Self::Map(d.decode_with(ctx)?))
1300            }
1301            _ => Err(minicbor::decode::Error::message(
1302                "invalid type for redeemers struct",
1303            )),
1304        }
1305    }
1306}
1307
1308impl<C> minicbor::Encode<C> for Redeemers {
1309    fn encode<W: minicbor::encode::Write>(
1310        &self,
1311        e: &mut minicbor::Encoder<W>,
1312        ctx: &mut C,
1313    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1314        match self {
1315            Self::List(x) => e.encode_with(x, ctx)?,
1316            Self::Map(x) => e.encode_with(x, ctx)?,
1317        };
1318
1319        Ok(())
1320    }
1321}
1322
1323pub use crate::alonzo::BootstrapWitness;
1324
1325#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
1326#[cbor(map)]
1327pub struct WitnessSet {
1328    #[n(0)]
1329    pub vkeywitness: Option<NonEmptySet<VKeyWitness>>,
1330
1331    #[n(1)]
1332    pub native_script: Option<NonEmptySet<NativeScript>>,
1333
1334    #[n(2)]
1335    pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
1336
1337    #[n(3)]
1338    pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
1339
1340    #[n(4)]
1341    pub plutus_data: Option<NonEmptySet<PlutusData>>,
1342
1343    #[n(5)]
1344    pub redeemer: Option<Redeemers>,
1345
1346    #[n(6)]
1347    pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
1348
1349    #[n(7)]
1350    pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
1351}
1352
1353#[derive(Encode, Decode, Debug, PartialEq, Clone)]
1354#[cbor(map)]
1355pub struct MintedWitnessSet<'b> {
1356    #[n(0)]
1357    pub vkeywitness: Option<NonEmptySet<VKeyWitness>>,
1358
1359    #[n(1)]
1360    pub native_script: Option<NonEmptySet<KeepRaw<'b, NativeScript>>>,
1361
1362    #[n(2)]
1363    pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
1364
1365    #[n(3)]
1366    pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
1367
1368    #[b(4)]
1369    pub plutus_data: Option<NonEmptySet<KeepRaw<'b, PlutusData>>>,
1370
1371    #[n(5)]
1372    pub redeemer: Option<KeepRaw<'b, Redeemers>>,
1373
1374    #[n(6)]
1375    pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
1376
1377    #[n(7)]
1378    pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
1379}
1380
1381impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
1382    fn from(x: MintedWitnessSet<'b>) -> Self {
1383        WitnessSet {
1384            vkeywitness: x.vkeywitness,
1385            native_script: x.native_script.map(Into::into),
1386            bootstrap_witness: x.bootstrap_witness,
1387            plutus_v1_script: x.plutus_v1_script,
1388            plutus_data: x.plutus_data.map(Into::into),
1389            redeemer: x.redeemer.map(|x| x.unwrap()),
1390            plutus_v2_script: x.plutus_v2_script,
1391            plutus_v3_script: x.plutus_v3_script,
1392        }
1393    }
1394}
1395
1396#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
1397#[cbor(map)]
1398pub struct PostAlonzoAuxiliaryData {
1399    #[n(0)]
1400    pub metadata: Option<Metadata>,
1401
1402    #[n(1)]
1403    pub native_scripts: Option<Vec<NativeScript>>,
1404
1405    #[n(2)]
1406    pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
1407
1408    #[n(3)]
1409    pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
1410
1411    #[n(4)]
1412    pub plutus_v3_scripts: Option<Vec<PlutusScript<3>>>,
1413}
1414
1415pub use crate::babbage::DatumHash;
1416
1417pub use crate::babbage::PseudoDatumOption;
1418
1419pub use crate::babbage::DatumOption;
1420
1421pub use crate::babbage::MintedDatumOption;
1422
1423#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
1424pub type PlutusV1Script = PlutusScript<1>;
1425
1426#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
1427pub type PlutusV2Script = PlutusScript<2>;
1428
1429#[deprecated(since = "0.31.0", note = "use `PlutusScript<3>` instead")]
1430pub type PlutusV3Script = PlutusScript<3>;
1431
1432// script = [ 0, native_script // 1, plutus_v1_script // 2, plutus_v2_script ]
1433#[derive(Debug, PartialEq, Eq, Clone)]
1434pub enum PseudoScript<T1> {
1435    NativeScript(T1),
1436    PlutusV1Script(PlutusScript<1>),
1437    PlutusV2Script(PlutusScript<2>),
1438    PlutusV3Script(PlutusScript<3>),
1439}
1440
1441// script_ref = #6.24(bytes .cbor script)
1442pub type ScriptRef = PseudoScript<NativeScript>;
1443
1444pub type MintedScriptRef<'b> = PseudoScript<KeepRaw<'b, NativeScript>>;
1445
1446impl<'b> From<MintedScriptRef<'b>> for ScriptRef {
1447    fn from(value: MintedScriptRef<'b>) -> Self {
1448        match value {
1449            PseudoScript::NativeScript(x) => Self::NativeScript(x.unwrap()),
1450            PseudoScript::PlutusV1Script(x) => Self::PlutusV1Script(x),
1451            PseudoScript::PlutusV2Script(x) => Self::PlutusV2Script(x),
1452            PseudoScript::PlutusV3Script(x) => Self::PlutusV3Script(x),
1453        }
1454    }
1455}
1456
1457// TODO: Remove in favour of multierascriptref
1458impl<'b> From<babbage::MintedScriptRef<'b>> for MintedScriptRef<'b> {
1459    fn from(value: babbage::MintedScriptRef<'b>) -> Self {
1460        match value {
1461            babbage::MintedScriptRef::NativeScript(x) => Self::NativeScript(x),
1462            babbage::MintedScriptRef::PlutusV1Script(x) => Self::PlutusV1Script(x),
1463            babbage::MintedScriptRef::PlutusV2Script(x) => Self::PlutusV2Script(x),
1464        }
1465    }
1466}
1467
1468impl<'b, C, T> minicbor::Decode<'b, C> for PseudoScript<T>
1469where
1470    T: minicbor::Decode<'b, ()>,
1471{
1472    fn decode(
1473        d: &mut minicbor::Decoder<'b>,
1474        _ctx: &mut C,
1475    ) -> Result<Self, minicbor::decode::Error> {
1476        d.array()?;
1477
1478        match d.u8()? {
1479            0 => Ok(Self::NativeScript(d.decode()?)),
1480            1 => Ok(Self::PlutusV1Script(d.decode()?)),
1481            2 => Ok(Self::PlutusV2Script(d.decode()?)),
1482            3 => Ok(Self::PlutusV3Script(d.decode()?)),
1483            x => Err(minicbor::decode::Error::message(format!(
1484                "invalid variant for script enum: {}",
1485                x
1486            ))),
1487        }
1488    }
1489}
1490
1491impl<C, T> minicbor::Encode<C> for PseudoScript<T>
1492where
1493    T: minicbor::Encode<C>,
1494{
1495    fn encode<W: minicbor::encode::Write>(
1496        &self,
1497        e: &mut minicbor::Encoder<W>,
1498        ctx: &mut C,
1499    ) -> Result<(), minicbor::encode::Error<W::Error>> {
1500        match self {
1501            Self::NativeScript(x) => e.encode_with((0, x), ctx)?,
1502            Self::PlutusV1Script(x) => e.encode_with((1, x), ctx)?,
1503            Self::PlutusV2Script(x) => e.encode_with((2, x), ctx)?,
1504            Self::PlutusV3Script(x) => e.encode_with((3, x), ctx)?,
1505        };
1506
1507        Ok(())
1508    }
1509}
1510
1511pub use crate::alonzo::AuxiliaryData;
1512
1513use crate::babbage::MintedHeader;
1514
1515#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
1516pub struct PseudoBlock<T1, T2, T3, T4>
1517where
1518    T4: std::clone::Clone,
1519{
1520    #[n(0)]
1521    pub header: T1,
1522
1523    #[b(1)]
1524    pub transaction_bodies: MaybeIndefArray<T2>,
1525
1526    #[n(2)]
1527    pub transaction_witness_sets: MaybeIndefArray<T3>,
1528
1529    #[n(3)]
1530    pub auxiliary_data_set: KeyValuePairs<TransactionIndex, T4>,
1531
1532    #[n(4)]
1533    pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
1534}
1535
1536pub type Block = PseudoBlock<Header, TransactionBody, WitnessSet, AuxiliaryData>;
1537
1538/// A memory representation of an already minted block
1539///
1540/// This structure is analogous to [Block], but it allows to retrieve the
1541/// original CBOR bytes for each structure that might require hashing. In this
1542/// way, we make sure that the resulting hash matches what exists on-chain.
1543pub type MintedBlock<'b> = PseudoBlock<
1544    KeepRaw<'b, MintedHeader<'b>>,
1545    KeepRaw<'b, MintedTransactionBody<'b>>,
1546    KeepRaw<'b, MintedWitnessSet<'b>>,
1547    KeepRaw<'b, AuxiliaryData>,
1548>;
1549
1550impl<'b> From<MintedBlock<'b>> for Block {
1551    fn from(x: MintedBlock<'b>) -> Self {
1552        Block {
1553            header: x.header.unwrap().into(),
1554            transaction_bodies: MaybeIndefArray::Def(
1555                x.transaction_bodies
1556                    .iter()
1557                    .cloned()
1558                    .map(|x| x.unwrap())
1559                    .map(TransactionBody::from)
1560                    .collect(),
1561            ),
1562            transaction_witness_sets: MaybeIndefArray::Def(
1563                x.transaction_witness_sets
1564                    .iter()
1565                    .cloned()
1566                    .map(|x| x.unwrap())
1567                    .map(WitnessSet::from)
1568                    .collect(),
1569            ),
1570            auxiliary_data_set: x
1571                .auxiliary_data_set
1572                .to_vec()
1573                .into_iter()
1574                .map(|(k, v)| (k, v.unwrap()))
1575                .collect::<Vec<_>>()
1576                .into(),
1577            invalid_transactions: x.invalid_transactions,
1578        }
1579    }
1580}
1581
1582#[derive(Clone, Serialize, Deserialize, Encode, Decode, Debug)]
1583pub struct PseudoTx<T1, T2, T3>
1584where
1585    T1: std::clone::Clone,
1586    T2: std::clone::Clone,
1587    T3: std::clone::Clone,
1588{
1589    #[n(0)]
1590    pub transaction_body: T1,
1591
1592    #[n(1)]
1593    pub transaction_witness_set: T2,
1594
1595    #[n(2)]
1596    pub success: bool,
1597
1598    #[n(3)]
1599    pub auxiliary_data: Nullable<T3>,
1600}
1601
1602pub type Tx = PseudoTx<TransactionBody, WitnessSet, AuxiliaryData>;
1603
1604pub type MintedTx<'b> = PseudoTx<
1605    KeepRaw<'b, MintedTransactionBody<'b>>,
1606    KeepRaw<'b, MintedWitnessSet<'b>>,
1607    KeepRaw<'b, AuxiliaryData>,
1608>;
1609
1610impl<'b> From<MintedTx<'b>> for Tx {
1611    fn from(x: MintedTx<'b>) -> Self {
1612        Tx {
1613            transaction_body: x.transaction_body.unwrap().into(),
1614            transaction_witness_set: x.transaction_witness_set.unwrap().into(),
1615            success: x.success,
1616            auxiliary_data: x.auxiliary_data.map(|x| x.unwrap()),
1617        }
1618    }
1619}
1620
1621#[cfg(test)]
1622mod tests {
1623    use pallas_codec::minicbor;
1624
1625    use super::MintedBlock;
1626
1627    type BlockWrapper<'b> = (u16, MintedBlock<'b>);
1628
1629    #[test]
1630    fn block_isomorphic_decoding_encoding() {
1631        let test_blocks = [
1632            include_str!("../../../test_data/conway1.block"),
1633            include_str!("../../../test_data/conway2.block"),
1634            // interesting block with extreme values
1635            include_str!("../../../test_data/conway3.block"),
1636            // interesting block with extreme values
1637            include_str!("../../../test_data/conway4.block"),
1638        ];
1639
1640        for (idx, block_str) in test_blocks.iter().enumerate() {
1641            println!("decoding test block {}", idx + 1);
1642            let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
1643
1644            let block: BlockWrapper = minicbor::decode(&bytes)
1645                .unwrap_or_else(|e| panic!("error decoding cbor for file {idx}: {e:?}"));
1646
1647            let bytes2 = minicbor::to_vec(block)
1648                .unwrap_or_else(|e| panic!("error encoding block cbor for file {idx}: {e:?}"));
1649
1650            assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
1651        }
1652    }
1653
1654    // #[test]
1655    // fn fragments_decoding() {
1656    //     // peculiar array of outputs used in an hydra transaction
1657    //     let bytes = hex::decode(hex).unwrap();
1658    //     let outputs =
1659    // Vec::<TransactionOutput>::decode_fragment(&bytes).unwrap();
1660    //
1661    //     dbg!(outputs);
1662    //
1663    //     // add any loose fragment tests here
1664    // }
1665}