Skip to main content

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};
8
9pub use pallas_codec::codec_by_datatype;
10
11pub use crate::{
12    AddrKeyhash, AssetName, Bytes, Coin, CostModel, DnsName, Epoch, ExUnits, GenesisDelegateHash,
13    Genesishash, Hash, IPv4, IPv6, KeepRaw, Metadata, Metadatum, MetadatumLabel, NetworkId,
14    NonEmptySet, NonZeroInt, Nonce, NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash,
15    PoolMetadata, PoolMetadataHash, Port, PositiveCoin, PositiveInterval, ProtocolVersion,
16    RationalNumber, Relay, RewardAccount, ScriptHash, Set, StakeCredential, TransactionIndex,
17    TransactionInput, UnitInterval, VrfCert, VrfKeyhash, plutus_data::*,
18};
19
20use crate::BTreeMap;
21
22use crate::babbage;
23
24pub use crate::babbage::HeaderBody;
25
26pub use crate::babbage::OperationalCert;
27
28pub use crate::babbage::Header;
29
30pub type Multiasset<A> = BTreeMap<PolicyId, BTreeMap<AssetName, A>>;
31
32pub type Mint = Multiasset<NonZeroInt>;
33
34#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
35pub enum Value {
36    Coin(Coin),
37    Multiasset(Coin, Multiasset<PositiveCoin>),
38}
39
40codec_by_datatype! {
41    Value,
42    U8 | U16 | U32 | U64 => Coin,
43    (coin, multi => Multiasset)
44}
45
46pub use crate::alonzo::TransactionOutput as LegacyTransactionOutput;
47
48pub type Withdrawals = BTreeMap<RewardAccount, Coin>;
49
50pub type RequiredSigners = NonEmptySet<AddrKeyhash>;
51
52#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
53#[cbor(flat)]
54pub enum Certificate {
55    #[n(0)]
56    StakeRegistration(#[n(0)] StakeCredential),
57    #[n(1)]
58    StakeDeregistration(#[n(0)] StakeCredential),
59    #[n(2)]
60    StakeDelegation(#[n(0)] StakeCredential, #[n(1)] PoolKeyhash),
61    #[n(3)]
62    PoolRegistration {
63        #[n(0)]
64        operator: PoolKeyhash,
65        #[n(1)]
66        vrf_keyhash: VrfKeyhash,
67        #[n(2)]
68        pledge: Coin,
69        #[n(3)]
70        cost: Coin,
71        #[n(4)]
72        margin: UnitInterval,
73        #[n(5)]
74        reward_account: RewardAccount,
75        #[n(6)]
76        pool_owners: Set<AddrKeyhash>,
77        #[n(7)]
78        relays: Vec<Relay>,
79        #[n(8)]
80        pool_metadata: Option<PoolMetadata>,
81    },
82    #[n(4)]
83    PoolRetirement(#[n(0)] PoolKeyhash, #[n(1)] Epoch),
84
85    #[n(7)]
86    Reg(#[n(0)] StakeCredential, #[n(1)] Coin),
87    #[n(8)]
88    UnReg(#[n(0)] StakeCredential, #[n(1)] Coin),
89    #[n(9)]
90    VoteDeleg(#[n(0)] StakeCredential, #[n(1)] DRep),
91    #[n(10)]
92    StakeVoteDeleg(#[n(0)] StakeCredential, #[n(1)] PoolKeyhash, #[n(2)] DRep),
93    #[n(11)]
94    StakeRegDeleg(#[n(0)] StakeCredential, #[n(1)] PoolKeyhash, #[n(2)] Coin),
95    #[n(12)]
96    VoteRegDeleg(#[n(0)] StakeCredential, #[n(1)] DRep, #[n(2)] Coin),
97    #[n(13)]
98    StakeVoteRegDeleg(
99        #[n(0)] StakeCredential,
100        #[n(1)] PoolKeyhash,
101        #[n(2)] DRep,
102        #[n(3)] Coin,
103    ),
104
105    #[n(14)]
106    AuthCommitteeHot(
107        #[n(0)] CommitteeColdCredential,
108        #[n(1)] CommitteeHotCredential,
109    ),
110    #[n(15)]
111    ResignCommitteeCold(#[n(0)] CommitteeColdCredential, #[n(1)] Option<Anchor>),
112    #[n(16)]
113    RegDRepCert(#[n(0)] DRepCredential, #[n(1)] Coin, #[n(2)] Option<Anchor>),
114    #[n(17)]
115    UnRegDRepCert(#[n(0)] DRepCredential, #[n(1)] Coin),
116    #[n(18)]
117    UpdateDRepCert(#[n(0)] DRepCredential, #[n(1)] Option<Anchor>),
118}
119
120#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
121#[cbor(flat)]
122pub enum DRep {
123    #[n(0)]
124    Key(#[n(0)] AddrKeyhash),
125    #[n(1)]
126    Script(#[n(0)] ScriptHash),
127    #[n(2)]
128    Abstain,
129    #[n(3)]
130    NoConfidence,
131}
132
133pub type DRepCredential = StakeCredential;
134
135pub type CommitteeColdCredential = StakeCredential;
136
137pub type CommitteeHotCredential = StakeCredential;
138
139#[derive(
140    Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash,
141)]
142#[cbor(index_only)]
143pub enum Language {
144    #[n(0)]
145    PlutusV1,
146
147    #[n(1)]
148    PlutusV2,
149
150    #[n(2)]
151    PlutusV3,
152}
153
154#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
155pub type CostMdls = CostModels;
156
157#[derive(Serialize, Deserialize, Encode, Debug, PartialEq, Eq, Clone)]
158#[cbor(map)]
159pub struct CostModels {
160    #[n(0)]
161    pub plutus_v1: Option<CostModel>,
162
163    #[n(1)]
164    pub plutus_v2: Option<CostModel>,
165
166    #[n(2)]
167    pub plutus_v3: Option<CostModel>,
168
169    #[cbor(skip)]
170    pub unknown: BTreeMap<u64, CostModel>,
171}
172
173impl<'b, C> minicbor::Decode<'b, C> for CostModels {
174    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
175        let models: BTreeMap<u64, CostModel> = d.decode_with(ctx)?;
176
177        let mut plutus_v1 = None;
178        let mut plutus_v2 = None;
179        let mut plutus_v3 = None;
180        let mut unknown: Vec<(u64, CostModel)> = Vec::new();
181
182        for (k, v) in models.iter() {
183            match k {
184                0 => plutus_v1 = Some(v.clone()),
185                1 => plutus_v2 = Some(v.clone()),
186                2 => plutus_v3 = Some(v.clone()),
187                _ => unknown.push((*k, v.clone())),
188            }
189        }
190
191        Ok(Self {
192            plutus_v1,
193            plutus_v2,
194            plutus_v3,
195            unknown: unknown.into_iter().collect(),
196        })
197    }
198}
199
200#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
201#[cbor(map)]
202pub struct ProtocolParamUpdate {
203    #[n(0)]
204    pub minfee_a: Option<u64>,
205    #[n(1)]
206    pub minfee_b: Option<u64>,
207    #[n(2)]
208    pub max_block_body_size: Option<u64>,
209    #[n(3)]
210    pub max_transaction_size: Option<u64>,
211    #[n(4)]
212    pub max_block_header_size: Option<u64>,
213    #[n(5)]
214    pub key_deposit: Option<Coin>,
215    #[n(6)]
216    pub pool_deposit: Option<Coin>,
217    #[n(7)]
218    pub maximum_epoch: Option<Epoch>,
219    #[n(8)]
220    pub desired_number_of_stake_pools: Option<u64>,
221    #[n(9)]
222    pub pool_pledge_influence: Option<RationalNumber>,
223    #[n(10)]
224    pub expansion_rate: Option<UnitInterval>,
225    #[n(11)]
226    pub treasury_growth_rate: Option<UnitInterval>,
227
228    #[n(16)]
229    pub min_pool_cost: Option<Coin>,
230    #[n(17)]
231    pub ada_per_utxo_byte: Option<Coin>,
232    #[n(18)]
233    pub cost_models_for_script_languages: Option<CostModels>,
234    #[n(19)]
235    pub execution_costs: Option<ExUnitPrices>,
236    #[n(20)]
237    pub max_tx_ex_units: Option<ExUnits>,
238    #[n(21)]
239    pub max_block_ex_units: Option<ExUnits>,
240    #[n(22)]
241    pub max_value_size: Option<u64>,
242    #[n(23)]
243    pub collateral_percentage: Option<u64>,
244    #[n(24)]
245    pub max_collateral_inputs: Option<u64>,
246
247    #[n(25)]
248    pub pool_voting_thresholds: Option<PoolVotingThresholds>,
249    #[n(26)]
250    pub drep_voting_thresholds: Option<DRepVotingThresholds>,
251    #[n(27)]
252    pub min_committee_size: Option<u64>,
253    #[n(28)]
254    pub committee_term_limit: Option<Epoch>,
255    #[n(29)]
256    pub governance_action_validity_period: Option<Epoch>,
257    #[n(30)]
258    pub governance_action_deposit: Option<Coin>,
259    #[n(31)]
260    pub drep_deposit: Option<Coin>,
261    #[n(32)]
262    pub drep_inactivity_period: Option<Epoch>,
263    #[n(33)]
264    pub minfee_refscript_cost_per_byte: Option<UnitInterval>,
265}
266
267#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
268pub struct Update {
269    #[n(0)]
270    pub proposed_protocol_parameter_updates: BTreeMap<Genesishash, ProtocolParamUpdate>,
271
272    #[n(1)]
273    pub epoch: Epoch,
274}
275
276#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
277pub struct PoolVotingThresholds {
278    #[n(0)]
279    pub motion_no_confidence: UnitInterval,
280    #[n(1)]
281    pub committee_normal: UnitInterval,
282    #[n(2)]
283    pub committee_no_confidence: UnitInterval,
284    #[n(3)]
285    pub hard_fork_initiation: UnitInterval,
286    #[n(4)]
287    pub security_voting_threshold: UnitInterval,
288}
289
290#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
291pub struct DRepVotingThresholds {
292    #[n(0)]
293    pub motion_no_confidence: UnitInterval,
294    #[n(1)]
295    pub committee_normal: UnitInterval,
296    #[n(2)]
297    pub committee_no_confidence: UnitInterval,
298    #[n(3)]
299    pub update_constitution: UnitInterval,
300    #[n(4)]
301    pub hard_fork_initiation: UnitInterval,
302    #[n(5)]
303    pub pp_network_group: UnitInterval,
304    #[n(6)]
305    pub pp_economic_group: UnitInterval,
306    #[n(7)]
307    pub pp_technical_group: UnitInterval,
308    #[n(8)]
309    pub pp_governance_group: UnitInterval,
310    #[n(9)]
311    pub treasury_withdrawal: UnitInterval,
312}
313
314#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
315#[cbor(map)]
316pub struct TransactionBody<'a> {
317    #[n(0)]
318    pub inputs: Set<TransactionInput>,
319
320    #[b(1)]
321    pub outputs: Vec<TransactionOutput<'a>>,
322
323    #[n(2)]
324    pub fee: Coin,
325
326    #[n(3)]
327    pub ttl: Option<u64>,
328
329    #[n(4)]
330    pub certificates: Option<NonEmptySet<Certificate>>,
331
332    #[n(5)]
333    pub withdrawals: Option<BTreeMap<RewardAccount, Coin>>,
334
335    #[n(7)]
336    pub auxiliary_data_hash: Option<Hash<32>>,
337
338    #[n(8)]
339    pub validity_interval_start: Option<u64>,
340
341    #[n(9)]
342    pub mint: Option<Multiasset<NonZeroInt>>,
343
344    #[n(11)]
345    pub script_data_hash: Option<Hash<32>>,
346
347    #[n(13)]
348    pub collateral: Option<NonEmptySet<TransactionInput>>,
349
350    #[n(14)]
351    pub required_signers: Option<RequiredSigners>,
352
353    #[n(15)]
354    pub network_id: Option<NetworkId>,
355
356    #[n(16)]
357    pub collateral_return: Option<TransactionOutput<'a>>,
358
359    #[n(17)]
360    pub total_collateral: Option<Coin>,
361
362    #[n(18)]
363    pub reference_inputs: Option<NonEmptySet<TransactionInput>>,
364
365    // -- NEW IN CONWAY
366    #[n(19)]
367    pub voting_procedures: Option<VotingProcedures>,
368
369    #[n(20)]
370    pub proposal_procedures: Option<NonEmptySet<ProposalProcedure>>,
371
372    #[n(21)]
373    pub treasury_value: Option<Coin>,
374
375    #[n(22)]
376    pub donation: Option<PositiveCoin>,
377}
378
379#[deprecated(since = "1.0.0-alpha", note = "use `TransactionBody` instead")]
380pub type MintedTransactionBody<'a> = TransactionBody<'a>;
381
382#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
383#[cbor(index_only)]
384pub enum Vote {
385    #[n(0)]
386    No,
387    #[n(1)]
388    Yes,
389    #[n(2)]
390    Abstain,
391}
392
393pub type VotingProcedures = BTreeMap<Voter, BTreeMap<GovActionId, VotingProcedure>>;
394
395#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
396pub struct VotingProcedure {
397    #[n(0)]
398    pub vote: Vote,
399    #[n(1)]
400    pub anchor: Option<Anchor>,
401}
402
403#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
404pub struct ProposalProcedure {
405    #[n(0)]
406    pub deposit: Coin,
407    #[n(1)]
408    pub reward_account: RewardAccount,
409    #[n(2)]
410    pub gov_action: GovAction,
411    #[n(3)]
412    pub anchor: Anchor,
413}
414
415#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
416#[cbor(flat)]
417pub enum GovAction {
418    #[n(0)]
419    ParameterChange(
420        #[n(0)] Option<GovActionId>,
421        #[n(1)] Box<ProtocolParamUpdate>,
422        #[n(2)] Option<ScriptHash>,
423    ),
424    #[n(1)]
425    HardForkInitiation(#[n(0)] Option<GovActionId>, #[n(1)] ProtocolVersion),
426    #[n(2)]
427    TreasuryWithdrawals(
428        #[n(0)] BTreeMap<RewardAccount, Coin>,
429        #[n(1)] Option<ScriptHash>,
430    ),
431    #[n(3)]
432    NoConfidence(#[n(0)] Option<GovActionId>),
433    #[n(4)]
434    UpdateCommittee(
435        #[n(0)] Option<GovActionId>,
436        #[n(1)] Set<CommitteeColdCredential>,
437        #[n(2)] BTreeMap<CommitteeColdCredential, Epoch>,
438        #[n(3)] UnitInterval,
439    ),
440    #[n(5)]
441    NewConstitution(#[n(0)] Option<GovActionId>, #[n(1)] Constitution),
442    #[n(6)]
443    Information,
444}
445
446#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
447pub struct Constitution {
448    #[n(0)]
449    pub anchor: Anchor,
450    #[n(1)]
451    pub guardrail_script: Option<ScriptHash>,
452}
453
454#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
455#[cbor(flat)]
456pub enum Voter {
457    #[n(1)]
458    ConstitutionalCommitteeScript(#[n(0)] ScriptHash),
459    #[n(0)]
460    ConstitutionalCommitteeKey(#[n(0)] AddrKeyhash),
461    #[n(3)]
462    DRepScript(#[n(0)] ScriptHash),
463    #[n(2)]
464    DRepKey(#[n(0)] AddrKeyhash),
465    #[n(4)]
466    StakePoolKey(#[n(0)] AddrKeyhash),
467}
468
469#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
470pub struct Anchor {
471    #[n(0)]
472    pub url: String,
473    #[n(1)]
474    pub content_hash: Hash<32>,
475}
476
477#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
478pub struct GovActionId {
479    #[n(0)]
480    pub transaction_id: Hash<32>,
481    #[n(1)]
482    pub action_index: u32,
483}
484
485pub type PostAlonzoTransactionOutput<'b> =
486    babbage::GenPostAlonzoTransactionOutput<'b, Value, ScriptRef<'b>>;
487
488#[deprecated(
489    since = "1.0.0-alpha",
490    note = "use `PostAlonzoTransactionOutput` instead"
491)]
492pub type MintedPostAlonzoTransactionOutput<'b> = PostAlonzoTransactionOutput<'b>;
493
494pub type TransactionOutput<'b> = babbage::GenTransactionOutput<'b, PostAlonzoTransactionOutput<'b>>;
495
496// FIXME: Repeated since macro does not handle type generics yet.
497codec_by_datatype! {
498    TransactionOutput<'b>,
499    Array | ArrayIndef => Legacy,
500    Map | MapIndef => PostAlonzo,
501    ()
502}
503
504#[deprecated(since = "1.0.0-alpha", note = "use `TransactionOutput` instead")]
505pub type MintedTransactionOutput<'b> = TransactionOutput<'b>;
506
507pub use crate::alonzo::VKeyWitness;
508
509pub use crate::alonzo::NativeScript;
510
511#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
512pub struct ExUnitPrices {
513    #[n(0)]
514    pub mem_price: RationalNumber,
515
516    #[n(1)]
517    pub step_price: RationalNumber,
518}
519
520#[derive(
521    Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord,
522)]
523#[cbor(index_only)]
524pub enum RedeemerTag {
525    #[n(0)]
526    Spend,
527    #[n(1)]
528    Mint,
529    #[n(2)]
530    Cert,
531    #[n(3)]
532    Reward,
533    #[n(4)]
534    Vote,
535    #[n(5)]
536    Propose,
537}
538
539#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
540pub struct Redeemer {
541    #[n(0)]
542    pub tag: RedeemerTag,
543
544    #[n(1)]
545    pub index: u32,
546
547    #[n(2)]
548    pub data: PlutusData,
549
550    #[n(3)]
551    pub ex_units: ExUnits,
552}
553
554#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
555pub struct RedeemersKey {
556    #[n(0)]
557    pub tag: RedeemerTag,
558    #[n(1)]
559    pub index: u32,
560}
561
562#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
563pub struct RedeemersValue {
564    #[n(0)]
565    pub data: PlutusData,
566    #[n(1)]
567    pub ex_units: ExUnits,
568}
569
570#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
571pub enum Redeemers {
572    List(Vec<Redeemer>),
573    Map(BTreeMap<RedeemersKey, RedeemersValue>),
574}
575
576codec_by_datatype! {
577    Redeemers,
578    Array | ArrayIndef => List,
579    Map | MapIndef => Map,
580    ()
581}
582
583impl From<BTreeMap<RedeemersKey, RedeemersValue>> for Redeemers {
584    fn from(value: BTreeMap<RedeemersKey, RedeemersValue>) -> Self {
585        Redeemers::Map(value)
586    }
587}
588
589pub use crate::alonzo::BootstrapWitness;
590
591#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
592#[cbor(map)]
593pub struct WitnessSet<'b> {
594    #[n(0)]
595    pub vkeywitness: Option<NonEmptySet<VKeyWitness>>,
596
597    #[n(1)]
598    pub native_script: Option<NonEmptySet<KeepRaw<'b, NativeScript>>>,
599
600    #[n(2)]
601    pub bootstrap_witness: Option<NonEmptySet<BootstrapWitness>>,
602
603    #[n(3)]
604    pub plutus_v1_script: Option<NonEmptySet<PlutusScript<1>>>,
605
606    #[b(4)]
607    pub plutus_data: Option<KeepRaw<'b, NonEmptySet<KeepRaw<'b, PlutusData>>>>,
608
609    #[n(5)]
610    pub redeemer: Option<KeepRaw<'b, Redeemers>>,
611
612    #[n(6)]
613    pub plutus_v2_script: Option<NonEmptySet<PlutusScript<2>>>,
614
615    #[n(7)]
616    pub plutus_v3_script: Option<NonEmptySet<PlutusScript<3>>>,
617}
618
619#[deprecated(since = "1.0.0-alpha", note = "use `WitnessSet` instead")]
620pub type MintedWitnessSet<'b> = WitnessSet<'b>;
621
622#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
623#[cbor(map)]
624pub struct PostAlonzoAuxiliaryData {
625    #[n(0)]
626    pub metadata: Option<Metadata>,
627
628    #[n(1)]
629    pub native_scripts: Option<Vec<NativeScript>>,
630
631    #[n(2)]
632    pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
633
634    #[n(3)]
635    pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
636
637    #[n(4)]
638    pub plutus_v3_scripts: Option<Vec<PlutusScript<3>>>,
639}
640
641pub use babbage::DatumHash;
642
643pub use babbage::DatumOption;
644
645#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
646pub type PlutusV1Script = PlutusScript<1>;
647
648#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
649pub type PlutusV2Script = PlutusScript<2>;
650
651#[deprecated(since = "0.31.0", note = "use `PlutusScript<3>` instead")]
652pub type PlutusV3Script = PlutusScript<3>;
653
654// script = [0, native_script // 1, plutus_v1_script // 2, plutus_v2_script //
655// 3, plutus_v3_script]
656#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
657#[cbor(flat)]
658pub enum ScriptRef<'b> {
659    #[n(0)]
660    NativeScript(#[b(0)] KeepRaw<'b, NativeScript>),
661    #[n(1)]
662    PlutusV1Script(#[n(0)] PlutusScript<1>),
663    #[n(2)]
664    PlutusV2Script(#[n(0)] PlutusScript<2>),
665    #[n(3)]
666    PlutusV3Script(#[n(0)] PlutusScript<3>),
667}
668
669// TODO: Remove in favour of multierascriptref
670impl<'b> From<babbage::ScriptRef<'b>> for ScriptRef<'b> {
671    fn from(value: babbage::ScriptRef<'b>) -> Self {
672        match value {
673            babbage::ScriptRef::NativeScript(x) => Self::NativeScript(x),
674            babbage::ScriptRef::PlutusV1Script(x) => Self::PlutusV1Script(x),
675            babbage::ScriptRef::PlutusV2Script(x) => Self::PlutusV2Script(x),
676        }
677    }
678}
679
680#[deprecated(since = "1.0.0-alpha", note = "use `ScriptRef` instead")]
681pub type MintedScriptRef<'b> = ScriptRef<'b>;
682
683pub use crate::alonzo::AuxiliaryData;
684
685/// A memory representation of an already minted block
686///
687/// This structure allows to retrieve the
688/// original CBOR bytes for each structure that might require hashing. In this
689/// way, we make sure that the resulting hash matches what exists on-chain.
690#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
691pub struct Block<'b> {
692    #[n(0)]
693    pub header: KeepRaw<'b, Header>,
694
695    #[b(1)]
696    pub transaction_bodies: Vec<KeepRaw<'b, TransactionBody<'b>>>,
697
698    #[n(2)]
699    pub transaction_witness_sets: Vec<KeepRaw<'b, WitnessSet<'b>>>,
700
701    #[n(3)]
702    pub auxiliary_data_set: BTreeMap<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
703
704    #[n(4)]
705    pub invalid_transactions: Option<Vec<TransactionIndex>>,
706}
707
708#[deprecated(since = "1.0.0-alpha", note = "use `Block` instead")]
709pub type MintedBlock<'b> = Block<'b>;
710
711#[derive(Clone, Serialize, Deserialize, Encode, Decode, Debug, PartialEq)]
712pub struct Tx<'b> {
713    #[b(0)]
714    pub transaction_body: KeepRaw<'b, TransactionBody<'b>>,
715
716    #[n(1)]
717    pub transaction_witness_set: KeepRaw<'b, WitnessSet<'b>>,
718
719    #[n(2)]
720    pub success: bool,
721
722    #[n(3)]
723    pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
724}
725
726impl Eq for Tx<'_> {}
727
728#[deprecated(since = "1.0.0-alpha", note = "use `Tx` instead")]
729pub type MintedTx<'b> = Tx<'b>;
730
731#[cfg(test)]
732mod tests {
733    use super::Block;
734    use pallas_codec::minicbor;
735
736    type BlockWrapper<'b> = (u16, Block<'b>);
737
738    #[cfg(test)]
739    mod tests_voter {
740        use super::super::Voter;
741        use crate::Hash;
742        use std::cmp::Ordering;
743        use test_case::test_case;
744
745        fn fake_hash(prefix: &str) -> Hash<28> {
746            let null_hash: [u8; 28] = [
747                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,
748            ];
749            Hash::from(&[prefix.as_bytes(), &null_hash].concat()[0..28])
750        }
751
752        fn cc_script(prefix: &str) -> Voter {
753            Voter::ConstitutionalCommitteeScript(fake_hash(prefix))
754        }
755
756        fn cc_key(prefix: &str) -> Voter {
757            Voter::ConstitutionalCommitteeKey(fake_hash(prefix))
758        }
759
760        fn drep_script(prefix: &str) -> Voter {
761            Voter::DRepScript(fake_hash(prefix))
762        }
763
764        fn drep_key(prefix: &str) -> Voter {
765            Voter::DRepKey(fake_hash(prefix))
766        }
767
768        fn spo(prefix: &str) -> Voter {
769            Voter::StakePoolKey(fake_hash(prefix))
770        }
771
772        #[test_case(cc_script("alice"), cc_script("alice") => Ordering::Equal)]
773        #[test_case(cc_script("alice"), cc_key("alice") => Ordering::Less)]
774        #[test_case(cc_script("alice"), drep_script("alice") => Ordering::Less)]
775        #[test_case(cc_script("alice"), drep_key("alice") => Ordering::Less)]
776        #[test_case(cc_script("alice"), spo("alice") => Ordering::Less)]
777        #[test_case(cc_script("bob"), cc_script("alice") => Ordering::Greater)]
778        #[test_case(drep_script("alice"), cc_script("alice") => Ordering::Greater)]
779        #[test_case(drep_script("alice"), cc_key("alice") => Ordering::Greater)]
780        #[test_case(drep_script("alice"), drep_script("alice") => Ordering::Equal)]
781        #[test_case(drep_script("alice"), drep_key("alice") => Ordering::Less)]
782        #[test_case(drep_script("alice"), spo("alice") => Ordering::Less)]
783        #[test_case(drep_script("bob"), drep_script("alice") => Ordering::Greater)]
784        fn voter_ordering(left: Voter, right: Voter) -> Ordering {
785            left.cmp(&right)
786        }
787    }
788
789    #[test]
790    fn block_isomorphic_decoding_encoding() {
791        let test_blocks = [
792            include_str!("../../../test_data/conway1.block"),
793            include_str!("../../../test_data/conway2.block"),
794            // interesting block with extreme values
795            include_str!("../../../test_data/conway3.block"),
796            // interesting block with extreme values
797            include_str!("../../../test_data/conway4.block"),
798            // peculiar block with hash-size issue
799            #[cfg(feature = "relaxed")]
800            include_str!("../../../test_data/conway8.block"),
801        ];
802
803        for (idx, block_str) in test_blocks.iter().enumerate() {
804            println!("decoding test block {}", idx + 1);
805            let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
806
807            let block: BlockWrapper = minicbor::decode(&bytes)
808                .unwrap_or_else(|e| panic!("error decoding cbor for file {idx}: {e:?}"));
809
810            let bytes2 = minicbor::to_vec(block)
811                .unwrap_or_else(|e| panic!("error encoding block cbor for file {idx}: {e:?}"));
812
813            assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
814        }
815    }
816
817    // #[test]
818    // fn fragments_decoding() {
819    //     // peculiar array of outputs used in an hydra transaction
820    //     let bytes = hex::decode(hex).unwrap();
821    //     let outputs =
822    // Vec::<TransactionOutput>::decode_fragment(&bytes).unwrap();
823    //
824    //     dbg!(outputs);
825    //
826    //     // add any loose fragment tests here
827    // }
828}