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 let size = d.array()?;
574
575 let assert_size = |expected| {
576 if expected != size.unwrap_or(expected) {
578 return Err(minicbor::decode::Error::message(
579 "unexpected array size in NativeScript",
580 ));
581 }
582 Ok(())
583 };
584
585 let variant = d.u32()?;
586
587 let script = match variant {
588 0 => {
589 assert_size(2)?;
590 Ok(NativeScript::ScriptPubkey(d.decode_with(ctx)?))
591 }
592 1 => {
593 assert_size(2)?;
594 Ok(NativeScript::ScriptAll(d.decode_with(ctx)?))
595 }
596 2 => {
597 assert_size(2)?;
598 Ok(NativeScript::ScriptAny(d.decode_with(ctx)?))
599 }
600 3 => {
601 assert_size(3)?;
602 Ok(NativeScript::ScriptNOfK(
603 d.decode_with(ctx)?,
604 d.decode_with(ctx)?,
605 ))
606 }
607 4 => {
608 assert_size(2)?;
609 Ok(NativeScript::InvalidBefore(d.decode_with(ctx)?))
610 }
611 5 => {
612 assert_size(2)?;
613 Ok(NativeScript::InvalidHereafter(d.decode_with(ctx)?))
614 }
615 _ => Err(minicbor::decode::Error::message(
616 "unknown variant id for native script",
617 )),
618 }?;
619
620 if size.is_none() {
621 let next = d.datatype()?;
622 if next != minicbor::data::Type::Break {
623 return Err(minicbor::decode::Error::type_mismatch(next));
624 }
625 }
626
627 Ok(script)
628 }
629}
630
631impl<C> minicbor::encode::Encode<C> for NativeScript {
632 fn encode<W: minicbor::encode::Write>(
633 &self,
634 e: &mut minicbor::Encoder<W>,
635 ctx: &mut C,
636 ) -> Result<(), minicbor::encode::Error<W::Error>> {
637 match self {
638 NativeScript::ScriptPubkey(v) => {
639 e.array(2)?;
640 e.encode_with(0, ctx)?;
641 e.encode_with(v, ctx)?;
642 }
643 NativeScript::ScriptAll(v) => {
644 e.array(2)?;
645 e.encode_with(1, ctx)?;
646 e.encode_with(v, ctx)?;
647 }
648 NativeScript::ScriptAny(v) => {
649 e.array(2)?;
650 e.encode_with(2, ctx)?;
651 e.encode_with(v, ctx)?;
652 }
653 NativeScript::ScriptNOfK(a, b) => {
654 e.array(3)?;
655 e.encode_with(3, ctx)?;
656 e.encode_with(a, ctx)?;
657 e.encode_with(b, ctx)?;
658 }
659 NativeScript::InvalidBefore(v) => {
660 e.array(2)?;
661 e.encode_with(4, ctx)?;
662 e.encode_with(v, ctx)?;
663 }
664 NativeScript::InvalidHereafter(v) => {
665 e.array(2)?;
666 e.encode_with(5, ctx)?;
667 e.encode_with(v, ctx)?;
668 }
669 }
670
671 Ok(())
672 }
673}
674
675#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
676#[cbor(index_only)]
677pub enum RedeemerTag {
678 #[n(0)]
679 Spend,
680 #[n(1)]
681 Mint,
682 #[n(2)]
683 Cert,
684 #[n(3)]
685 Reward,
686}
687
688#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
689pub struct Redeemer {
690 #[n(0)]
691 pub tag: RedeemerTag,
692
693 #[n(1)]
694 pub index: u32,
695
696 #[n(2)]
697 pub data: PlutusData,
698
699 #[n(3)]
700 pub ex_units: ExUnits,
701}
702
703#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
704pub struct RedeemerPointer {
705 #[n(0)]
706 pub tag: RedeemerTag,
707
708 #[n(1)]
709 pub index: u32,
710}
711
712#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
720pub struct BootstrapWitness {
721 #[n(0)]
722 pub public_key: Bytes,
723
724 #[n(1)]
725 pub signature: Bytes,
726
727 #[n(2)]
728 pub chain_code: Bytes,
729
730 #[n(3)]
731 pub attributes: Bytes,
732}
733
734#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
735#[cbor(map)]
736pub struct WitnessSet {
737 #[n(0)]
738 pub vkeywitness: Option<Vec<VKeyWitness>>,
739
740 #[n(1)]
741 pub native_script: Option<Vec<NativeScript>>,
742
743 #[n(2)]
744 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
745
746 #[n(3)]
747 pub plutus_script: Option<Vec<PlutusScript<1>>>,
748
749 #[n(4)]
750 pub plutus_data: Option<Vec<PlutusData>>,
751
752 #[n(5)]
753 pub redeemer: Option<Vec<Redeemer>>,
754}
755
756#[derive(Encode, Decode, Debug, PartialEq, Clone)]
757#[cbor(map)]
758pub struct MintedWitnessSet<'b> {
759 #[n(0)]
760 pub vkeywitness: Option<Vec<VKeyWitness>>,
761
762 #[n(1)]
763 pub native_script: Option<Vec<KeepRaw<'b, NativeScript>>>,
764
765 #[n(2)]
766 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
767
768 #[n(3)]
769 pub plutus_script: Option<Vec<PlutusScript<1>>>,
770
771 #[b(4)]
772 pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
773
774 #[n(5)]
775 pub redeemer: Option<Vec<Redeemer>>,
776}
777
778impl<'b> From<MintedWitnessSet<'b>> for WitnessSet {
779 #[allow(deprecated)]
780 fn from(x: MintedWitnessSet<'b>) -> Self {
781 WitnessSet {
782 vkeywitness: x.vkeywitness,
783 native_script: x
784 .native_script
785 .map(|x| x.into_iter().map(|x| x.unwrap()).collect()),
786 bootstrap_witness: x.bootstrap_witness,
787 plutus_script: x.plutus_script,
788 plutus_data: x
789 .plutus_data
790 .map(|x| x.into_iter().map(|x| x.unwrap()).collect()),
791 redeemer: x.redeemer,
792 }
793 }
794}
795
796#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
797#[cbor(map)]
798pub struct PostAlonzoAuxiliaryData {
799 #[n(0)]
800 pub metadata: Option<Metadata>,
801
802 #[n(1)]
803 pub native_scripts: Option<Vec<NativeScript>>,
804
805 #[n(2)]
806 pub plutus_scripts: Option<Vec<PlutusScript<1>>>,
807}
808
809#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
810pub struct ShelleyMaAuxiliaryData {
811 #[n(0)]
812 pub transaction_metadata: Metadata,
813
814 #[n(1)]
815 pub auxiliary_scripts: Option<Vec<NativeScript>>,
816}
817
818#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
819pub enum AuxiliaryData {
820 Shelley(Metadata),
821 ShelleyMa(ShelleyMaAuxiliaryData),
822 PostAlonzo(PostAlonzoAuxiliaryData),
823}
824
825impl<'b, C> minicbor::Decode<'b, C> for AuxiliaryData {
826 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
827 match d.datatype()? {
828 minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
829 Ok(AuxiliaryData::Shelley(d.decode_with(ctx)?))
830 }
831 minicbor::data::Type::Array => Ok(AuxiliaryData::ShelleyMa(d.decode_with(ctx)?)),
832 minicbor::data::Type::Tag => {
833 d.tag()?;
834 Ok(AuxiliaryData::PostAlonzo(d.decode_with(ctx)?))
835 }
836 _ => Err(minicbor::decode::Error::message(
837 "Can't infer variant from data type for AuxiliaryData",
838 )),
839 }
840 }
841}
842
843impl<C> minicbor::Encode<C> for AuxiliaryData {
844 fn encode<W: minicbor::encode::Write>(
845 &self,
846 e: &mut minicbor::Encoder<W>,
847 ctx: &mut C,
848 ) -> Result<(), minicbor::encode::Error<W::Error>> {
849 match self {
850 AuxiliaryData::Shelley(m) => {
851 e.encode_with(m, ctx)?;
852 }
853 AuxiliaryData::ShelleyMa(m) => {
854 e.encode_with(m, ctx)?;
855 }
856 AuxiliaryData::PostAlonzo(v) => {
857 e.tag(Tag::new(259))?;
859 e.encode_with(v, ctx)?;
860 }
861 };
862
863 Ok(())
864 }
865}
866
867#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
868pub struct Block {
869 #[n(0)]
870 pub header: Header,
871
872 #[b(1)]
873 pub transaction_bodies: Vec<TransactionBody>,
874
875 #[n(2)]
876 pub transaction_witness_sets: Vec<WitnessSet>,
877
878 #[n(3)]
879 pub auxiliary_data_set: KeyValuePairs<TransactionIndex, AuxiliaryData>,
880
881 #[n(4)]
882 pub invalid_transactions: Option<Vec<TransactionIndex>>,
883}
884
885#[derive(Encode, Decode, Debug, PartialEq, Clone)]
891pub struct MintedBlock<'b> {
892 #[n(0)]
893 pub header: KeepRaw<'b, MintedHeader<'b>>,
894
895 #[b(1)]
896 pub transaction_bodies: MaybeIndefArray<KeepRaw<'b, TransactionBody>>,
897
898 #[n(2)]
899 pub transaction_witness_sets: MaybeIndefArray<KeepRaw<'b, MintedWitnessSet<'b>>>,
900
901 #[n(3)]
902 pub auxiliary_data_set: KeyValuePairs<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
903
904 #[n(4)]
905 pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
906}
907
908impl<'b> From<MintedBlock<'b>> for Block {
909 fn from(x: MintedBlock<'b>) -> Self {
910 Block {
911 header: x.header.unwrap().into(),
912 transaction_bodies: x
913 .transaction_bodies
914 .to_vec()
915 .into_iter()
916 .map(|x| x.unwrap())
917 .collect(),
918 transaction_witness_sets: x
919 .transaction_witness_sets
920 .to_vec()
921 .into_iter()
922 .map(|x| x.unwrap())
923 .map(WitnessSet::from)
924 .collect(),
925 auxiliary_data_set: x
926 .auxiliary_data_set
927 .to_vec()
928 .into_iter()
929 .map(|(k, v)| (k, v.unwrap()))
930 .collect::<Vec<_>>()
931 .into(),
932 invalid_transactions: x.invalid_transactions.map(|x| x.into()),
933 }
934 }
935}
936
937#[derive(Serialize, Deserialize, Encode, Decode, Debug)]
938pub struct Tx {
939 #[n(0)]
940 pub transaction_body: TransactionBody,
941
942 #[n(1)]
943 pub transaction_witness_set: WitnessSet,
944
945 #[n(2)]
946 pub success: bool,
947
948 #[n(3)]
949 pub auxiliary_data: Nullable<AuxiliaryData>,
950}
951
952#[derive(Encode, Decode, Debug, Clone)]
953pub struct MintedTx<'b> {
954 #[b(0)]
955 pub transaction_body: KeepRaw<'b, TransactionBody>,
956
957 #[n(1)]
958 pub transaction_witness_set: KeepRaw<'b, MintedWitnessSet<'b>>,
959
960 #[n(2)]
961 pub success: bool,
962
963 #[n(3)]
964 pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
965}
966
967#[cfg(test)]
968mod tests {
969 use pallas_codec::minicbor::{self, to_vec};
970
971 use crate::{alonzo::PlutusData, Fragment};
972
973 use super::{Header, MintedBlock, NativeScript};
974
975 type BlockWrapper<'b> = (u16, MintedBlock<'b>);
976
977 #[test]
978 fn native_script_encode_n_of_k() {
979 let script = NativeScript::ScriptNOfK(1, vec![]);
980 let bytes = minicbor::to_vec(script).unwrap();
981 assert_eq!(&hex::encode(&bytes), "83030180");
982 }
983
984 #[test]
985 fn native_script_decode_indef() {
986 let mut bytes = vec![0x9f, 0x02, 0x80]; let result: Result<NativeScript, _> = minicbor::decode(&bytes);
989
990 assert!(
991 result.is_err(),
992 "should have failed but yielded: {result:#?}"
993 );
994
995 bytes.push(0xFF);
996
997 assert_eq!(
998 minicbor::decode(&bytes).map_err(|e| e.to_string()),
999 Ok(NativeScript::ScriptAny(vec![]))
1000 );
1001 }
1002
1003 #[test]
1004 fn block_isomorphic_decoding_encoding() {
1005 let test_blocks = vec![
1006 include_str!("../../../test_data/alonzo1.block"),
1007 include_str!("../../../test_data/alonzo2.block"),
1008 include_str!("../../../test_data/alonzo3.block"),
1009 include_str!("../../../test_data/alonzo4.block"),
1010 include_str!("../../../test_data/alonzo5.block"),
1011 include_str!("../../../test_data/alonzo6.block"),
1012 include_str!("../../../test_data/alonzo7.block"),
1013 include_str!("../../../test_data/alonzo8.block"),
1014 include_str!("../../../test_data/alonzo9.block"),
1015 include_str!("../../../test_data/alonzo10.block"),
1017 include_str!("../../../test_data/alonzo11.block"),
1019 include_str!("../../../test_data/alonzo12.block"),
1022 include_str!("../../../test_data/alonzo13.block"),
1024 include_str!("../../../test_data/alonzo14.block"),
1027 include_str!("../../../test_data/alonzo15.block"),
1029 include_str!("../../../test_data/alonzo16.block"),
1031 include_str!("../../../test_data/alonzo17.block"),
1033 include_str!("../../../test_data/alonzo18.block"),
1035 include_str!("../../../test_data/alonzo18.block"),
1037 include_str!("../../../test_data/alonzo19.block"),
1039 include_str!("../../../test_data/alonzo20.block"),
1041 include_str!("../../../test_data/alonzo21.block"),
1043 include_str!("../../../test_data/alonzo22.block"),
1045 include_str!("../../../test_data/alonzo23.block"),
1047 include_str!("../../../test_data/alonzo27.block"),
1049 ];
1050
1051 for (idx, block_str) in test_blocks.iter().enumerate() {
1052 println!("decoding test block {}", idx + 1);
1053 let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
1054
1055 let block: BlockWrapper = minicbor::decode(&bytes[..])
1056 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
1057
1058 let bytes2 = to_vec(block)
1059 .unwrap_or_else(|_| panic!("error encoding block cbor for file {idx}"));
1060
1061 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
1062 }
1063 }
1064
1065 #[test]
1066 fn header_isomorphic_decoding_encoding() {
1067 let test_headers = [
1068 include_str!("../../../test_data/alonzo26.header"),
1070 ];
1071
1072 for (idx, header_str) in test_headers.iter().enumerate() {
1073 println!("decoding test header {}", idx + 1);
1074 let bytes = hex::decode(header_str).unwrap_or_else(|_| panic!("bad header file {idx}"));
1075
1076 let header: Header = minicbor::decode(&bytes[..])
1077 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
1078
1079 let bytes2 = to_vec(header)
1080 .unwrap_or_else(|_| panic!("error encoding header cbor for file {idx}"));
1081
1082 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
1083 }
1084 }
1085
1086 #[test]
1087 fn plutus_data_isomorphic_decoding_encoding() {
1088 let datas = [
1089 "d87980",
1091 "a201d87980029f000102ff",
1093 "9f000102ff",
1095 "d87e9fa201d87980029f000102ffd87e9fa3a201d87980029f000102ffd87a809f000102ffa201d87980029f000102ff809f01ffd87980d8799f0001ffffff",
1097 "d87e9f809f01ffa0a201d8798002d87b9f02ffff",
1099 "58206969696969696969696969696969696969696969696969696969696969696969",
1101 "5f58406969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696943696969ff",
1103 "40"
1105 ];
1106 for data_hex in datas {
1107 let data_bytes = hex::decode(data_hex).unwrap();
1108 let data = PlutusData::decode_fragment(&data_bytes).unwrap();
1109 assert_eq!(data.encode_fragment().unwrap(), data_bytes);
1110 }
1111 }
1112}