1use serde::{Deserialize, Serialize};
6
7use pallas_codec::minicbor::{self, data::Tag, Decode, Encode};
8
9pub use crate::{
10 plutus_data::*, AddrKeyhash, AssetName, Bytes, Coin, CostModel, DatumHash, DnsName, Epoch,
11 ExUnitPrices, ExUnits, GenesisDelegateHash, Genesishash, Hash, IPv4, IPv6, Int, KeepRaw,
12 KeyValuePairs, MaybeIndefArray, Metadata, Metadatum, MetadatumLabel, NetworkId, Nonce,
13 NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash, PoolMetadata, PoolMetadataHash,
14 Port, PositiveInterval, ProtocolVersion, RationalNumber, Relay, RewardAccount, ScriptHash,
15 StakeCredential, TransactionIndex, TransactionInput, UnitInterval, VrfCert, VrfKeyhash,
16};
17
18#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
19pub struct HeaderBody {
20 #[n(0)]
21 pub block_number: u64,
22
23 #[n(1)]
24 pub slot: u64,
25
26 #[n(2)]
27 pub prev_hash: Option<Hash<32>>,
28
29 #[n(3)]
30 pub issuer_vkey: Bytes,
31
32 #[n(4)]
33 pub vrf_vkey: Bytes,
34
35 #[n(5)]
36 pub nonce_vrf: VrfCert,
37
38 #[n(6)]
39 pub leader_vrf: VrfCert,
40
41 #[n(7)]
42 pub block_body_size: u64,
43
44 #[n(8)]
45 pub block_body_hash: Hash<32>,
46
47 #[n(9)]
48 pub operational_cert_hot_vkey: Bytes,
49
50 #[n(10)]
51 pub operational_cert_sequence_number: u64,
52
53 #[n(11)]
54 pub operational_cert_kes_period: u64,
55
56 #[n(12)]
57 pub operational_cert_sigma: Bytes,
58
59 #[n(13)]
60 pub protocol_major: u64,
61
62 #[n(14)]
63 pub protocol_minor: u64,
64}
65
66pub type MintedHeaderBody<'a> = KeepRaw<'a, HeaderBody>;
67
68#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
69pub struct PseudoHeader<T1> {
70 #[n(0)]
71 pub header_body: T1,
72
73 #[n(1)]
74 pub body_signature: Bytes,
75}
76
77pub type Header = PseudoHeader<HeaderBody>;
78
79pub type MintedHeader<'a> = KeepRaw<'a, PseudoHeader<MintedHeaderBody<'a>>>;
80
81impl<'a> From<MintedHeader<'a>> for Header {
82 fn from(x: MintedHeader<'a>) -> Self {
83 let x = x.unwrap();
84 Self {
85 header_body: x.header_body.into(),
86 body_signature: x.body_signature,
87 }
88 }
89}
90
91impl<'a> From<MintedHeaderBody<'a>> for HeaderBody {
92 fn from(x: MintedHeaderBody<'a>) -> Self {
93 x.unwrap()
94 }
95}
96
97pub type Multiasset<A> = KeyValuePairs<PolicyId, KeyValuePairs<AssetName, A>>;
98
99pub type Mint = Multiasset<i64>;
100
101#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
102pub enum Value {
103 Coin(Coin),
104 Multiasset(Coin, Multiasset<Coin>),
105}
106
107impl<'b, C> minicbor::decode::Decode<'b, C> for Value {
108 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
109 match d.datatype()? {
110 minicbor::data::Type::U8 => Ok(Value::Coin(d.decode_with(ctx)?)),
111 minicbor::data::Type::U16 => Ok(Value::Coin(d.decode_with(ctx)?)),
112 minicbor::data::Type::U32 => Ok(Value::Coin(d.decode_with(ctx)?)),
113 minicbor::data::Type::U64 => Ok(Value::Coin(d.decode_with(ctx)?)),
114 minicbor::data::Type::Array => {
115 d.array()?;
116 let coin = d.decode_with(ctx)?;
117 let multiasset = d.decode_with(ctx)?;
118 Ok(Value::Multiasset(coin, multiasset))
119 }
120 _ => Err(minicbor::decode::Error::message(
121 "unknown cbor data type for Alonzo Value enum",
122 )),
123 }
124 }
125}
126
127impl<C> minicbor::encode::Encode<C> for Value {
128 fn encode<W: minicbor::encode::Write>(
129 &self,
130 e: &mut minicbor::Encoder<W>,
131 ctx: &mut C,
132 ) -> Result<(), minicbor::encode::Error<W::Error>> {
133 match self {
135 Value::Coin(coin) => {
136 e.encode_with(coin, ctx)?;
137 }
138 Value::Multiasset(coin, other) => {
139 e.array(2)?;
140 e.encode_with(coin, ctx)?;
141 e.encode_with(other, ctx)?;
142 }
143 };
144
145 Ok(())
146 }
147}
148
149#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
150pub struct TransactionOutput {
151 #[n(0)]
152 pub address: Bytes,
153
154 #[n(1)]
155 pub amount: Value,
156
157 #[n(2)]
158 pub datum_hash: Option<DatumHash>,
159}
160
161#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
169pub enum InstantaneousRewardSource {
170 Reserves,
171 Treasury,
172}
173
174impl<'b, C> minicbor::decode::Decode<'b, C> for InstantaneousRewardSource {
175 fn decode(
176 d: &mut minicbor::Decoder<'b>,
177 _ctx: &mut C,
178 ) -> Result<Self, minicbor::decode::Error> {
179 let variant = d.u32()?;
180
181 match variant {
182 0 => Ok(Self::Reserves),
183 1 => Ok(Self::Treasury),
184 _ => Err(minicbor::decode::Error::message("invalid funds variant")),
185 }
186 }
187}
188
189impl<C> minicbor::encode::Encode<C> for InstantaneousRewardSource {
190 fn encode<W: minicbor::encode::Write>(
191 &self,
192 e: &mut minicbor::Encoder<W>,
193 _ctx: &mut C,
194 ) -> Result<(), minicbor::encode::Error<W::Error>> {
195 let variant = match self {
196 Self::Reserves => 0,
197 Self::Treasury => 1,
198 };
199
200 e.u32(variant)?;
201
202 Ok(())
203 }
204}
205
206#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
207pub enum InstantaneousRewardTarget {
208 StakeCredentials(KeyValuePairs<StakeCredential, i64>),
209 OtherAccountingPot(Coin),
210}
211
212impl<'b, C> minicbor::decode::Decode<'b, C> for InstantaneousRewardTarget {
213 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
214 let datatype = d.datatype()?;
215
216 match datatype {
217 minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
218 let a = d.decode_with(ctx)?;
219 Ok(Self::StakeCredentials(a))
220 }
221 _ => {
222 let a = d.decode_with(ctx)?;
223 Ok(Self::OtherAccountingPot(a))
224 }
225 }
226 }
227}
228
229impl<C> minicbor::encode::Encode<C> for InstantaneousRewardTarget {
230 fn encode<W: minicbor::encode::Write>(
231 &self,
232 e: &mut minicbor::Encoder<W>,
233 ctx: &mut C,
234 ) -> Result<(), minicbor::encode::Error<W::Error>> {
235 match self {
236 InstantaneousRewardTarget::StakeCredentials(a) => {
237 e.encode_with(a, ctx)?;
238 Ok(())
239 }
240 InstantaneousRewardTarget::OtherAccountingPot(a) => {
241 e.encode_with(a, ctx)?;
242 Ok(())
243 }
244 }
245 }
246}
247
248#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
249#[cbor()]
250pub struct MoveInstantaneousReward {
251 #[n(0)]
252 pub source: InstantaneousRewardSource,
253
254 #[n(1)]
255 pub target: InstantaneousRewardTarget,
256}
257
258pub type Withdrawals = KeyValuePairs<RewardAccount, Coin>;
259
260pub type RequiredSigners = Vec<AddrKeyhash>;
261
262#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
263pub enum Certificate {
264 StakeRegistration(StakeCredential),
265 StakeDeregistration(StakeCredential),
266 StakeDelegation(StakeCredential, PoolKeyhash),
267 PoolRegistration {
268 operator: PoolKeyhash,
269 vrf_keyhash: VrfKeyhash,
270 pledge: Coin,
271 cost: Coin,
272 margin: UnitInterval,
273 reward_account: RewardAccount,
274 pool_owners: Vec<AddrKeyhash>,
275 relays: Vec<Relay>,
276 pool_metadata: Nullable<PoolMetadata>,
277 },
278 PoolRetirement(PoolKeyhash, Epoch),
279 GenesisKeyDelegation(Genesishash, GenesisDelegateHash, VrfKeyhash),
280 MoveInstantaneousRewardsCert(MoveInstantaneousReward),
281}
282
283impl<'b, C> minicbor::decode::Decode<'b, C> for Certificate {
284 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
285 d.array()?;
286 let variant = d.u16()?;
287
288 match variant {
289 0 => {
290 let a = d.decode_with(ctx)?;
291 Ok(Certificate::StakeRegistration(a))
292 }
293 1 => {
294 let a = d.decode_with(ctx)?;
295 Ok(Certificate::StakeDeregistration(a))
296 }
297 2 => {
298 let a = d.decode_with(ctx)?;
299 let b = d.decode_with(ctx)?;
300 Ok(Certificate::StakeDelegation(a, b))
301 }
302 3 => {
303 let operator = d.decode_with(ctx)?;
304 let vrf_keyhash = d.decode_with(ctx)?;
305 let pledge = d.decode_with(ctx)?;
306 let cost = d.decode_with(ctx)?;
307 let margin = d.decode_with(ctx)?;
308 let reward_account = d.decode_with(ctx)?;
309 let pool_owners = d.decode_with(ctx)?;
310 let relays = d.decode_with(ctx)?;
311 let pool_metadata = d.decode_with(ctx)?;
312
313 Ok(Certificate::PoolRegistration {
314 operator,
315 vrf_keyhash,
316 pledge,
317 cost,
318 margin,
319 reward_account,
320 pool_owners,
321 relays,
322 pool_metadata,
323 })
324 }
325 4 => {
326 let a = d.decode_with(ctx)?;
327 let b = d.decode_with(ctx)?;
328 Ok(Certificate::PoolRetirement(a, b))
329 }
330 5 => {
331 let a = d.decode_with(ctx)?;
332 let b = d.decode_with(ctx)?;
333 let c = d.decode_with(ctx)?;
334 Ok(Certificate::GenesisKeyDelegation(a, b, c))
335 }
336 6 => {
337 let a = d.decode_with(ctx)?;
338 Ok(Certificate::MoveInstantaneousRewardsCert(a))
339 }
340 _ => Err(minicbor::decode::Error::message(
341 "unknown variant id for certificate",
342 )),
343 }
344 }
345}
346
347impl<C> minicbor::encode::Encode<C> for Certificate {
348 fn encode<W: minicbor::encode::Write>(
349 &self,
350 e: &mut minicbor::Encoder<W>,
351 ctx: &mut C,
352 ) -> Result<(), minicbor::encode::Error<W::Error>> {
353 match self {
354 Certificate::StakeRegistration(a) => {
355 e.array(2)?;
356 e.u16(0)?;
357 e.encode_with(a, ctx)?;
358
359 Ok(())
360 }
361 Certificate::StakeDeregistration(a) => {
362 e.array(2)?;
363 e.u16(1)?;
364 e.encode_with(a, ctx)?;
365
366 Ok(())
367 }
368 Certificate::StakeDelegation(a, b) => {
369 e.array(3)?;
370 e.u16(2)?;
371 e.encode_with(a, ctx)?;
372 e.encode_with(b, ctx)?;
373
374 Ok(())
375 }
376 Certificate::PoolRegistration {
377 operator,
378 vrf_keyhash,
379 pledge,
380 cost,
381 margin,
382 reward_account,
383 pool_owners,
384 relays,
385 pool_metadata,
386 } => {
387 e.array(10)?;
388 e.u16(3)?;
389
390 e.encode_with(operator, ctx)?;
391 e.encode_with(vrf_keyhash, ctx)?;
392 e.encode_with(pledge, ctx)?;
393 e.encode_with(cost, ctx)?;
394 e.encode_with(margin, ctx)?;
395 e.encode_with(reward_account, ctx)?;
396 e.encode_with(pool_owners, ctx)?;
397 e.encode_with(relays, ctx)?;
398 e.encode_with(pool_metadata, ctx)?;
399
400 Ok(())
401 }
402 Certificate::PoolRetirement(a, b) => {
403 e.array(3)?;
404 e.u16(4)?;
405 e.encode_with(a, ctx)?;
406 e.encode_with(b, ctx)?;
407
408 Ok(())
409 }
410 Certificate::GenesisKeyDelegation(a, b, c) => {
411 e.array(4)?;
412 e.u16(5)?;
413 e.encode_with(a, ctx)?;
414 e.encode_with(b, ctx)?;
415 e.encode_with(c, ctx)?;
416
417 Ok(())
418 }
419 Certificate::MoveInstantaneousRewardsCert(a) => {
420 e.array(2)?;
421 e.u16(6)?;
422 e.encode_with(a, ctx)?;
423
424 Ok(())
425 }
426 }
427 }
428}
429
430#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
431#[cbor(index_only)]
432pub enum Language {
433 #[n(0)]
434 PlutusV1,
435}
436
437#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
438pub type CostMdls = CostModels;
439
440pub type CostModels = KeyValuePairs<Language, CostModel>;
441
442#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
443#[cbor(map)]
444pub struct ProtocolParamUpdate {
445 #[n(0)]
446 pub minfee_a: Option<u32>,
447 #[n(1)]
448 pub minfee_b: Option<u32>,
449 #[n(2)]
450 pub max_block_body_size: Option<u32>,
451 #[n(3)]
452 pub max_transaction_size: Option<u32>,
453 #[n(4)]
454 pub max_block_header_size: Option<u32>,
455 #[n(5)]
456 pub key_deposit: Option<Coin>,
457 #[n(6)]
458 pub pool_deposit: Option<Coin>,
459 #[n(7)]
460 pub maximum_epoch: Option<Epoch>,
461 #[n(8)]
462 pub desired_number_of_stake_pools: Option<u32>,
463 #[n(9)]
464 pub pool_pledge_influence: Option<RationalNumber>,
465 #[n(10)]
466 pub expansion_rate: Option<UnitInterval>,
467 #[n(11)]
468 pub treasury_growth_rate: Option<UnitInterval>,
469 #[n(12)]
470 pub decentralization_constant: Option<UnitInterval>,
471 #[n(13)]
472 pub extra_entropy: Option<Nonce>,
473 #[n(14)]
474 pub protocol_version: Option<ProtocolVersion>,
475 #[n(16)]
476 pub min_pool_cost: Option<Coin>,
477 #[n(17)]
478 pub ada_per_utxo_byte: Option<Coin>,
479 #[n(18)]
480 pub cost_models_for_script_languages: Option<CostModels>,
481 #[n(19)]
482 pub execution_costs: Option<ExUnitPrices>,
483 #[n(20)]
484 pub max_tx_ex_units: Option<ExUnits>,
485 #[n(21)]
486 pub max_block_ex_units: Option<ExUnits>,
487 #[n(22)]
488 pub max_value_size: Option<u32>,
489 #[n(23)]
490 pub collateral_percentage: Option<u32>,
491 #[n(24)]
492 pub max_collateral_inputs: Option<u32>,
493}
494
495#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
496pub struct Update {
497 #[n(0)]
498 pub proposed_protocol_parameter_updates: KeyValuePairs<Genesishash, ProtocolParamUpdate>,
499
500 #[n(1)]
501 pub epoch: Epoch,
502}
503
504#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
507#[cbor(map)]
508pub struct TransactionBody {
509 #[n(0)]
510 pub inputs: Vec<TransactionInput>,
511
512 #[n(1)]
513 pub outputs: Vec<TransactionOutput>,
514
515 #[n(2)]
516 pub fee: u64,
517
518 #[n(3)]
519 pub ttl: Option<u64>,
520
521 #[n(4)]
522 pub certificates: Option<Vec<Certificate>>,
523
524 #[n(5)]
525 pub withdrawals: Option<Withdrawals>,
526
527 #[n(6)]
528 pub update: Option<Update>,
529
530 #[n(7)]
531 pub auxiliary_data_hash: Option<Bytes>,
532
533 #[n(8)]
534 pub validity_interval_start: Option<u64>,
535
536 #[n(9)]
537 pub mint: Option<Multiasset<i64>>,
538
539 #[n(11)]
540 pub script_data_hash: Option<Hash<32>>,
541
542 #[n(13)]
543 pub collateral: Option<Vec<TransactionInput>>,
544
545 #[n(14)]
546 pub required_signers: Option<RequiredSigners>,
547
548 #[n(15)]
549 pub network_id: Option<NetworkId>,
550}
551
552#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
553pub struct VKeyWitness {
554 #[n(0)]
555 pub vkey: Bytes,
556
557 #[n(1)]
558 pub signature: Bytes,
559}
560
561#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
562pub enum NativeScript {
563 ScriptPubkey(AddrKeyhash),
564 ScriptAll(Vec<NativeScript>),
565 ScriptAny(Vec<NativeScript>),
566 ScriptNOfK(u32, Vec<NativeScript>),
567 InvalidBefore(u64),
568 InvalidHereafter(u64),
569}
570
571impl<'b, C> minicbor::decode::Decode<'b, C> for NativeScript {
572 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
573 d.array()?;
574 let variant = d.u32()?;
575
576 match variant {
577 0 => Ok(NativeScript::ScriptPubkey(d.decode_with(ctx)?)),
578 1 => Ok(NativeScript::ScriptAll(d.decode_with(ctx)?)),
579 2 => Ok(NativeScript::ScriptAny(d.decode_with(ctx)?)),
580 3 => Ok(NativeScript::ScriptNOfK(
581 d.decode_with(ctx)?,
582 d.decode_with(ctx)?,
583 )),
584 4 => Ok(NativeScript::InvalidBefore(d.decode_with(ctx)?)),
585 5 => Ok(NativeScript::InvalidHereafter(d.decode_with(ctx)?)),
586 _ => Err(minicbor::decode::Error::message(
587 "unknown variant id for native script",
588 )),
589 }
590 }
591}
592
593impl<C> minicbor::encode::Encode<C> for NativeScript {
594 fn encode<W: minicbor::encode::Write>(
595 &self,
596 e: &mut minicbor::Encoder<W>,
597 ctx: &mut C,
598 ) -> Result<(), minicbor::encode::Error<W::Error>> {
599 e.array(2)?;
600
601 match self {
602 NativeScript::ScriptPubkey(v) => {
603 e.encode_with(0, ctx)?;
604 e.encode_with(v, ctx)?;
605 }
606 NativeScript::ScriptAll(v) => {
607 e.encode_with(1, ctx)?;
608 e.encode_with(v, ctx)?;
609 }
610 NativeScript::ScriptAny(v) => {
611 e.encode_with(2, ctx)?;
612 e.encode_with(v, ctx)?;
613 }
614 NativeScript::ScriptNOfK(a, b) => {
615 e.encode_with(3, ctx)?;
616 e.encode_with(a, ctx)?;
617 e.encode_with(b, ctx)?;
618 }
619 NativeScript::InvalidBefore(v) => {
620 e.encode_with(4, ctx)?;
621 e.encode_with(v, ctx)?;
622 }
623 NativeScript::InvalidHereafter(v) => {
624 e.encode_with(5, ctx)?;
625 e.encode_with(v, ctx)?;
626 }
627 }
628
629 Ok(())
630 }
631}
632
633#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
634#[cbor(index_only)]
635pub enum RedeemerTag {
636 #[n(0)]
637 Spend,
638 #[n(1)]
639 Mint,
640 #[n(2)]
641 Cert,
642 #[n(3)]
643 Reward,
644}
645
646#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
647pub struct Redeemer {
648 #[n(0)]
649 pub tag: RedeemerTag,
650
651 #[n(1)]
652 pub index: u32,
653
654 #[n(2)]
655 pub data: PlutusData,
656
657 #[n(3)]
658 pub ex_units: ExUnits,
659}
660
661#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
662pub struct RedeemerPointer {
663 #[n(0)]
664 pub tag: RedeemerTag,
665
666 #[n(1)]
667 pub index: u32,
668}
669
670#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
678pub struct BootstrapWitness {
679 #[n(0)]
680 pub public_key: Bytes,
681
682 #[n(1)]
683 pub signature: Bytes,
684
685 #[n(2)]
686 pub chain_code: Bytes,
687
688 #[n(3)]
689 pub attributes: Bytes,
690}
691
692#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
693#[cbor(map)]
694pub struct WitnessSet {
695 #[n(0)]
696 pub vkeywitness: Option<Vec<VKeyWitness>>,
697
698 #[n(1)]
699 pub native_script: Option<Vec<NativeScript>>,
700
701 #[n(2)]
702 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
703
704 #[n(3)]
705 pub plutus_script: Option<Vec<PlutusScript<1>>>,
706
707 #[n(4)]
708 pub plutus_data: Option<Vec<PlutusData>>,
709
710 #[n(5)]
711 pub redeemer: Option<Vec<Redeemer>>,
712}
713
714#[derive(Encode, Decode, Debug, PartialEq, Clone)]
715#[cbor(map)]
716pub struct MintedWitnessSet<'b> {
717 #[n(0)]
718 pub vkeywitness: Option<Vec<VKeyWitness>>,
719
720 #[n(1)]
721 pub native_script: Option<Vec<KeepRaw<'b, NativeScript>>>,
722
723 #[n(2)]
724 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
725
726 #[n(3)]
727 pub plutus_script: Option<Vec<PlutusScript<1>>>,
728
729 #[b(4)]
730 pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
731
732 #[n(5)]
733 pub redeemer: Option<Vec<Redeemer>>,
734}
735
736impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
737 #[allow(deprecated)]
738 fn from(x: MintedWitnessSet<'b>) -> Self {
739 WitnessSet {
740 vkeywitness: x.vkeywitness,
741 native_script: x
742 .native_script
743 .map(|x| x.into_iter().map(|x| x.unwrap()).collect()),
744 bootstrap_witness: x.bootstrap_witness,
745 plutus_script: x.plutus_script,
746 plutus_data: x
747 .plutus_data
748 .map(|x| x.into_iter().map(|x| x.unwrap()).collect()),
749 redeemer: x.redeemer,
750 }
751 }
752}
753
754#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
755#[cbor(map)]
756pub struct PostAlonzoAuxiliaryData {
757 #[n(0)]
758 pub metadata: Option<Metadata>,
759
760 #[n(1)]
761 pub native_scripts: Option<Vec<NativeScript>>,
762
763 #[n(2)]
764 pub plutus_scripts: Option<Vec<PlutusScript<1>>>,
765}
766
767#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
768pub struct ShelleyMaAuxiliaryData {
769 #[n(0)]
770 pub transaction_metadata: Metadata,
771
772 #[n(1)]
773 pub auxiliary_scripts: Option<Vec<NativeScript>>,
774}
775
776#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
777pub enum AuxiliaryData {
778 Shelley(Metadata),
779 ShelleyMa(ShelleyMaAuxiliaryData),
780 PostAlonzo(PostAlonzoAuxiliaryData),
781}
782
783impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData {
784 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
785 match d.datatype()? {
786 minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
787 Ok(AuxiliaryData::Shelley(d.decode_with(ctx)?))
788 }
789 minicbor::data::Type::Array => Ok(AuxiliaryData::ShelleyMa(d.decode_with(ctx)?)),
790 minicbor::data::Type::Tag => {
791 d.tag()?;
792 Ok(AuxiliaryData::PostAlonzo(d.decode_with(ctx)?))
793 }
794 _ => Err(minicbor::decode::Error::message(
795 "Can't infer variant from data type for AuxiliaryData",
796 )),
797 }
798 }
799}
800
801impl<C> minicbor::Encode<C> for AuxiliaryData {
802 fn encode<W: minicbor::encode::Write>(
803 &self,
804 e: &mut minicbor::Encoder<W>,
805 ctx: &mut C,
806 ) -> Result<(), minicbor::encode::Error<W::Error>> {
807 match self {
808 AuxiliaryData::Shelley(m) => {
809 e.encode_with(m, ctx)?;
810 }
811 AuxiliaryData::ShelleyMa(m) => {
812 e.encode_with(m, ctx)?;
813 }
814 AuxiliaryData::PostAlonzo(v) => {
815 e.tag(Tag::new(259))?;
817 e.encode_with(v, ctx)?;
818 }
819 };
820
821 Ok(())
822 }
823}
824
825#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
826pub struct Block {
827 #[n(0)]
828 pub header: Header,
829
830 #[b(1)]
831 pub transaction_bodies: Vec<TransactionBody>,
832
833 #[n(2)]
834 pub transaction_witness_sets: Vec<WitnessSet>,
835
836 #[n(3)]
837 pub auxiliary_data_set: KeyValuePairs<TransactionIndex, AuxiliaryData>,
838
839 #[n(4)]
840 pub invalid_transactions: Option<Vec<TransactionIndex>>,
841}
842
843#[derive(Encode, Decode, Debug, PartialEq, Clone)]
849pub struct MintedBlock<'b> {
850 #[n(0)]
851 pub header: KeepRaw<'b, MintedHeader<'b>>,
852
853 #[b(1)]
854 pub transaction_bodies: MaybeIndefArray<KeepRaw<'b, TransactionBody>>,
855
856 #[n(2)]
857 pub transaction_witness_sets: MaybeIndefArray<KeepRaw<'b, MintedWitnessSet<'b>>>,
858
859 #[n(3)]
860 pub auxiliary_data_set: KeyValuePairs<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
861
862 #[n(4)]
863 pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
864}
865
866impl<'b> From<MintedBlock<'b>> for Block {
867 fn from(x: MintedBlock<'b>) -> Self {
868 Block {
869 header: x.header.unwrap().into(),
870 transaction_bodies: x
871 .transaction_bodies
872 .to_vec()
873 .into_iter()
874 .map(|x| x.unwrap())
875 .collect(),
876 transaction_witness_sets: x
877 .transaction_witness_sets
878 .to_vec()
879 .into_iter()
880 .map(|x| x.unwrap())
881 .map(WitnessSet::from)
882 .collect(),
883 auxiliary_data_set: x
884 .auxiliary_data_set
885 .to_vec()
886 .into_iter()
887 .map(|(k, v)| (k, v.unwrap()))
888 .collect::<Vec<_>>()
889 .into(),
890 invalid_transactions: x.invalid_transactions.map(|x| x.into()),
891 }
892 }
893}
894
895#[derive(Serialize, Deserialize, Encode, Decode, Debug)]
896pub struct Tx {
897 #[n(0)]
898 pub transaction_body: TransactionBody,
899
900 #[n(1)]
901 pub transaction_witness_set: WitnessSet,
902
903 #[n(2)]
904 pub success: bool,
905
906 #[n(3)]
907 pub auxiliary_data: Nullable<AuxiliaryData>,
908}
909
910#[derive(Encode, Decode, Debug, Clone)]
911pub struct MintedTx<'b> {
912 #[b(0)]
913 pub transaction_body: KeepRaw<'b, TransactionBody>,
914
915 #[n(1)]
916 pub transaction_witness_set: KeepRaw<'b, MintedWitnessSet<'b>>,
917
918 #[n(2)]
919 pub success: bool,
920
921 #[n(3)]
922 pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
923}
924
925#[cfg(test)]
926mod tests {
927 use pallas_codec::minicbor::{self, to_vec};
928
929 use crate::{alonzo::PlutusData, Fragment};
930
931 use super::{Header, MintedBlock};
932
933 type BlockWrapper<'b> = (u16, MintedBlock<'b>);
934
935 #[test]
936 fn block_isomorphic_decoding_encoding() {
937 let test_blocks = vec![
938 include_str!("../../../test_data/alonzo1.block"),
939 include_str!("../../../test_data/alonzo2.block"),
940 include_str!("../../../test_data/alonzo3.block"),
941 include_str!("../../../test_data/alonzo4.block"),
942 include_str!("../../../test_data/alonzo5.block"),
943 include_str!("../../../test_data/alonzo6.block"),
944 include_str!("../../../test_data/alonzo7.block"),
945 include_str!("../../../test_data/alonzo8.block"),
946 include_str!("../../../test_data/alonzo9.block"),
947 include_str!("../../../test_data/alonzo10.block"),
949 include_str!("../../../test_data/alonzo11.block"),
951 include_str!("../../../test_data/alonzo12.block"),
954 include_str!("../../../test_data/alonzo13.block"),
956 include_str!("../../../test_data/alonzo14.block"),
959 include_str!("../../../test_data/alonzo15.block"),
961 include_str!("../../../test_data/alonzo16.block"),
963 include_str!("../../../test_data/alonzo17.block"),
965 include_str!("../../../test_data/alonzo18.block"),
967 include_str!("../../../test_data/alonzo18.block"),
969 include_str!("../../../test_data/alonzo19.block"),
971 include_str!("../../../test_data/alonzo20.block"),
973 include_str!("../../../test_data/alonzo21.block"),
975 include_str!("../../../test_data/alonzo22.block"),
977 include_str!("../../../test_data/alonzo23.block"),
979 include_str!("../../../test_data/alonzo27.block"),
981 ];
982
983 for (idx, block_str) in test_blocks.iter().enumerate() {
984 println!("decoding test block {}", idx + 1);
985 let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
986
987 let block: BlockWrapper = minicbor::decode(&bytes[..])
988 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
989
990 let bytes2 = to_vec(block)
991 .unwrap_or_else(|_| panic!("error encoding block cbor for file {idx}"));
992
993 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
994 }
995 }
996
997 #[test]
998 fn header_isomorphic_decoding_encoding() {
999 let test_headers = [
1000 include_str!("../../../test_data/alonzo26.header"),
1002 ];
1003
1004 for (idx, header_str) in test_headers.iter().enumerate() {
1005 println!("decoding test header {}", idx + 1);
1006 let bytes = hex::decode(header_str).unwrap_or_else(|_| panic!("bad header file {idx}"));
1007
1008 let header: Header = minicbor::decode(&bytes[..])
1009 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
1010
1011 let bytes2 = to_vec(header)
1012 .unwrap_or_else(|_| panic!("error encoding header cbor for file {idx}"));
1013
1014 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
1015 }
1016 }
1017
1018 #[test]
1019 fn plutus_data_isomorphic_decoding_encoding() {
1020 let datas = [
1021 "d87980",
1023 "a201d87980029f000102ff",
1025 "9f000102ff",
1027 "d87e9fa201d87980029f000102ffd87e9fa3a201d87980029f000102ffd87a809f000102ffa201d87980029f000102ff809f01ffd87980d8799f0001ffffff",
1029 "d87e9f809f01ffa0a201d8798002d87b9f02ffff",
1031 "58206969696969696969696969696969696969696969696969696969696969696969",
1033 "5f58406969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696943696969ff",
1035 "40"
1037 ];
1038 for data_hex in datas {
1039 let data_bytes = hex::decode(data_hex).unwrap();
1040 let data = PlutusData::decode_fragment(&data_bytes).unwrap();
1041 assert_eq!(data.encode_fragment().unwrap(), data_bytes);
1042 }
1043 }
1044}