1use 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, DatumHash, DnsName, Epoch, ExUnitPrices,
13 ExUnits, GenesisDelegateHash, Genesishash, Hash, IPv4, IPv6, Int, KeepRaw, Metadata, Metadatum,
14 MetadatumLabel, NetworkId, Nonce, NonceVariant, Nullable, PlutusScript, PolicyId, PoolKeyhash,
15 PoolMetadata, PoolMetadataHash, Port, PositiveInterval, ProtocolVersion, RationalNumber, Relay,
16 RewardAccount, ScriptHash, StakeCredential, TransactionIndex, TransactionInput, UnitInterval,
17 VrfCert, VrfKeyhash, plutus_data::*,
18};
19
20use crate::BTreeMap;
21
22#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
23pub struct HeaderBody {
24 #[n(0)]
25 pub block_number: u64,
26
27 #[n(1)]
28 pub slot: u64,
29
30 #[n(2)]
31 pub prev_hash: Option<Hash<32>>,
32
33 #[n(3)]
34 pub issuer_vkey: Bytes,
35
36 #[n(4)]
37 pub vrf_vkey: Bytes,
38
39 #[n(5)]
40 pub nonce_vrf: VrfCert,
41
42 #[n(6)]
43 pub leader_vrf: VrfCert,
44
45 #[n(7)]
46 pub block_body_size: u64,
47
48 #[n(8)]
49 pub block_body_hash: Hash<32>,
50
51 #[n(9)]
52 pub operational_cert_hot_vkey: Bytes,
53
54 #[n(10)]
55 pub operational_cert_sequence_number: u64,
56
57 #[n(11)]
58 pub operational_cert_kes_period: u64,
59
60 #[n(12)]
61 pub operational_cert_sigma: Bytes,
62
63 #[n(13)]
64 pub protocol_major: u64,
65
66 #[n(14)]
67 pub protocol_minor: u64,
68}
69
70#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
71pub struct Header {
72 #[n(0)]
73 pub header_body: HeaderBody,
74
75 #[n(1)]
76 pub body_signature: Bytes,
77}
78
79#[deprecated(since = "1.0.0-alpha", note = "use `KeepRaw<'_, Header>` instead")]
80pub type MintedHeader<'a> = KeepRaw<'a, Header>;
81
82pub type Multiasset<A> = BTreeMap<PolicyId, BTreeMap<AssetName, A>>;
83
84pub type Mint = Multiasset<i64>;
85
86#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
87pub enum Value {
88 Coin(Coin),
89 Multiasset(Coin, Multiasset<Coin>),
90}
91
92codec_by_datatype! {
93 Value,
94 U8 | U16 | U32 | U64 => Coin,
95 (coin, multi => Multiasset)
96}
97
98#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
99pub struct TransactionOutput {
100 #[n(0)]
101 pub address: Bytes,
102
103 #[n(1)]
104 pub amount: Value,
105
106 #[n(2)]
107 pub datum_hash: Option<DatumHash>,
108}
109
110#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
118#[cbor(index_only)]
119pub enum InstantaneousRewardSource {
120 #[n(0)]
121 Reserves,
122 #[n(1)]
123 Treasury,
124}
125
126#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
127pub enum InstantaneousRewardTarget {
128 StakeCredentials(BTreeMap<StakeCredential, i64>),
129 OtherAccountingPot(Coin),
130}
131
132codec_by_datatype! {
133 InstantaneousRewardTarget,
134 Map | MapIndef => StakeCredentials,
135 U8 | U16 | U32 | U64 | I8 | I16 | I32 | I64 | Int => OtherAccountingPot,
136 ()
137}
138
139#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
140#[cbor()]
141pub struct MoveInstantaneousReward {
142 #[n(0)]
143 pub source: InstantaneousRewardSource,
144
145 #[n(1)]
146 pub target: InstantaneousRewardTarget,
147}
148
149pub type Withdrawals = BTreeMap<RewardAccount, Coin>;
150
151pub type RequiredSigners = Vec<AddrKeyhash>;
152
153#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Encode, Decode)]
154#[cbor(flat)]
155pub enum Certificate {
156 #[n(0)]
157 StakeRegistration(#[n(0)] StakeCredential),
158 #[n(1)]
159 StakeDeregistration(#[n(0)] StakeCredential),
160 #[n(2)]
161 StakeDelegation(#[n(0)] StakeCredential, #[n(1)] PoolKeyhash),
162 #[n(3)]
163 PoolRegistration {
164 #[n(0)]
165 operator: PoolKeyhash,
166 #[n(1)]
167 vrf_keyhash: VrfKeyhash,
168 #[n(2)]
169 pledge: Coin,
170 #[n(3)]
171 cost: Coin,
172 #[n(4)]
173 margin: UnitInterval,
174 #[n(5)]
175 reward_account: RewardAccount,
176 #[n(6)]
177 pool_owners: Vec<AddrKeyhash>,
178 #[n(7)]
179 relays: Vec<Relay>,
180 #[n(8)]
181 pool_metadata: Option<PoolMetadata>,
182 },
183 #[n(4)]
184 PoolRetirement(#[n(0)] PoolKeyhash, #[n(1)] Epoch),
185 #[n(5)]
186 GenesisKeyDelegation(
187 #[n(0)] Genesishash,
188 #[n(1)] GenesisDelegateHash,
189 #[n(2)] VrfKeyhash,
190 ),
191 #[n(6)]
192 MoveInstantaneousRewardsCert(#[n(0)] MoveInstantaneousReward),
193}
194
195#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
196#[cbor(index_only)]
197pub enum Language {
198 #[n(0)]
199 PlutusV1,
200}
201
202#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
203pub type CostMdls = CostModels;
204
205pub type CostModels = BTreeMap<Language, CostModel>;
206
207#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
208#[cbor(map)]
209pub struct ProtocolParamUpdate {
210 #[n(0)]
211 pub minfee_a: Option<u32>,
212 #[n(1)]
213 pub minfee_b: Option<u32>,
214 #[n(2)]
215 pub max_block_body_size: Option<u32>,
216 #[n(3)]
217 pub max_transaction_size: Option<u32>,
218 #[n(4)]
219 pub max_block_header_size: Option<u32>,
220 #[n(5)]
221 pub key_deposit: Option<Coin>,
222 #[n(6)]
223 pub pool_deposit: Option<Coin>,
224 #[n(7)]
225 pub maximum_epoch: Option<Epoch>,
226 #[n(8)]
227 pub desired_number_of_stake_pools: Option<u32>,
228 #[n(9)]
229 pub pool_pledge_influence: Option<RationalNumber>,
230 #[n(10)]
231 pub expansion_rate: Option<UnitInterval>,
232 #[n(11)]
233 pub treasury_growth_rate: Option<UnitInterval>,
234 #[n(12)]
235 pub decentralization_constant: Option<UnitInterval>,
236 #[n(13)]
237 pub extra_entropy: Option<Nonce>,
238 #[n(14)]
239 pub protocol_version: Option<ProtocolVersion>,
240 #[n(16)]
241 pub min_pool_cost: Option<Coin>,
242 #[n(17)]
243 pub ada_per_utxo_byte: Option<Coin>,
244 #[n(18)]
245 pub cost_models_for_script_languages: Option<CostModels>,
246 #[n(19)]
247 pub execution_costs: Option<ExUnitPrices>,
248 #[n(20)]
249 pub max_tx_ex_units: Option<ExUnits>,
250 #[n(21)]
251 pub max_block_ex_units: Option<ExUnits>,
252 #[n(22)]
253 pub max_value_size: Option<u32>,
254 #[n(23)]
255 pub collateral_percentage: Option<u32>,
256 #[n(24)]
257 pub max_collateral_inputs: Option<u32>,
258}
259
260#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
261pub struct Update {
262 #[n(0)]
263 pub proposed_protocol_parameter_updates: BTreeMap<Genesishash, ProtocolParamUpdate>,
264
265 #[n(1)]
266 pub epoch: Epoch,
267}
268
269#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
272#[cbor(map)]
273pub struct TransactionBody {
274 #[n(0)]
275 pub inputs: Vec<TransactionInput>,
276
277 #[n(1)]
278 pub outputs: Vec<TransactionOutput>,
279
280 #[n(2)]
281 pub fee: u64,
282
283 #[n(3)]
284 pub ttl: Option<u64>,
285
286 #[n(4)]
287 pub certificates: Option<Vec<Certificate>>,
288
289 #[n(5)]
290 pub withdrawals: Option<Withdrawals>,
291
292 #[n(6)]
293 pub update: Option<Update>,
294
295 #[n(7)]
296 pub auxiliary_data_hash: Option<Hash<32>>,
297
298 #[n(8)]
299 pub validity_interval_start: Option<u64>,
300
301 #[n(9)]
302 pub mint: Option<Multiasset<i64>>,
303
304 #[n(11)]
305 pub script_data_hash: Option<Hash<32>>,
306
307 #[n(13)]
308 pub collateral: Option<Vec<TransactionInput>>,
309
310 #[n(14)]
311 pub required_signers: Option<RequiredSigners>,
312
313 #[n(15)]
314 pub network_id: Option<NetworkId>,
315}
316
317#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
318pub struct VKeyWitness {
319 #[n(0)]
320 pub vkey: Bytes,
321
322 #[n(1)]
323 pub signature: Bytes,
324}
325
326#[derive(Serialize, Deserialize, Debug, Eq)]
333pub enum NativeScript {
334 ScriptPubkey(AddrKeyhash),
335 ScriptAll(Vec<NativeScript>),
336 ScriptAny(Vec<NativeScript>),
337 ScriptNOfK(i64, Vec<NativeScript>),
340 InvalidBefore(u64),
341 InvalidHereafter(u64),
342}
343
344#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
345#[cbor(index_only)]
346pub enum RedeemerTag {
347 #[n(0)]
348 Spend,
349 #[n(1)]
350 Mint,
351 #[n(2)]
352 Cert,
353 #[n(3)]
354 Reward,
355}
356
357#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
358pub struct Redeemer {
359 #[n(0)]
360 pub tag: RedeemerTag,
361
362 #[n(1)]
363 pub index: u32,
364
365 #[n(2)]
366 pub data: PlutusData,
367
368 #[n(3)]
369 pub ex_units: ExUnits,
370}
371
372#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, Copy)]
373pub struct RedeemerPointer {
374 #[n(0)]
375 pub tag: RedeemerTag,
376
377 #[n(1)]
378 pub index: u32,
379}
380
381#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
389pub struct BootstrapWitness {
390 #[n(0)]
391 pub public_key: Bytes,
392
393 #[n(1)]
394 pub signature: Bytes,
395
396 #[n(2)]
397 pub chain_code: Bytes,
398
399 #[n(3)]
400 pub attributes: Bytes,
401}
402
403#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
404#[cbor(map)]
405pub struct WitnessSet<'b> {
406 #[n(0)]
407 pub vkeywitness: Option<Vec<VKeyWitness>>,
408
409 #[n(1)]
410 pub native_script: Option<Vec<KeepRaw<'b, NativeScript>>>,
411
412 #[n(2)]
413 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
414
415 #[n(3)]
416 pub plutus_script: Option<Vec<PlutusScript<1>>>,
417
418 #[b(4)]
419 pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
420
421 #[n(5)]
422 pub redeemer: Option<Vec<Redeemer>>,
423}
424
425#[deprecated(since = "1.0.0-alpha", note = "use `WitnessSet` instead")]
426pub type MintedWitnessSet<'b> = WitnessSet<'b>;
427
428#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone, Eq)]
429#[cbor(map, tag(259))]
430pub struct PostAlonzoAuxiliaryData {
431 #[n(0)]
432 pub metadata: Option<Metadata>,
433
434 #[n(1)]
435 pub native_scripts: Option<Vec<NativeScript>>,
436
437 #[n(2)]
438 pub plutus_scripts: Option<Vec<PlutusScript<1>>>,
439}
440
441#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone, Eq)]
442pub struct ShelleyMaAuxiliaryData {
443 #[n(0)]
444 pub transaction_metadata: Metadata,
445
446 #[n(1)]
447 pub auxiliary_scripts: Option<Vec<NativeScript>>,
448}
449
450#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
451pub enum AuxiliaryData {
452 Shelley(Metadata),
453 ShelleyMa(ShelleyMaAuxiliaryData),
454 PostAlonzo(PostAlonzoAuxiliaryData),
455}
456
457codec_by_datatype! {
458 AuxiliaryData,
459 Map | MapIndef => Shelley,
460 Array | ArrayIndef => ShelleyMa,
461 Tag => PostAlonzo,
462 ()
463}
464
465#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
471pub struct Block<'b> {
472 #[n(0)]
473 pub header: KeepRaw<'b, Header>,
474
475 #[b(1)]
476 pub transaction_bodies: Vec<KeepRaw<'b, TransactionBody>>,
477
478 #[n(2)]
479 pub transaction_witness_sets: Vec<KeepRaw<'b, WitnessSet<'b>>>,
480
481 #[n(3)]
482 pub auxiliary_data_set: BTreeMap<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
483
484 #[n(4)]
485 pub invalid_transactions: Option<Vec<TransactionIndex>>,
486}
487
488#[deprecated(since = "1.0.0-alpha", note = "use `Block` instead")]
489pub type MintedBlock<'b> = Block<'b>;
490
491#[derive(Encode, Decode, Debug, Clone)]
492pub struct Tx<'b> {
493 #[b(0)]
494 pub transaction_body: KeepRaw<'b, TransactionBody>,
495
496 #[n(1)]
497 pub transaction_witness_set: KeepRaw<'b, WitnessSet<'b>>,
498
499 #[n(2)]
500 pub success: bool,
501
502 #[n(3)]
503 pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
504}
505
506#[deprecated(since = "1.0.0-alpha", note = "use `Tx` instead")]
507pub type MintedTx<'b> = Tx<'b>;
508
509#[cfg(test)]
510mod tests {
511 use pallas_codec::minicbor::{self, to_vec};
512
513 use crate::{Fragment, alonzo::PlutusData};
514
515 use super::{Block, Header};
516
517 type BlockWrapper<'b> = (u16, Block<'b>);
518
519 #[test]
520 fn block_isomorphic_decoding_encoding() {
521 let test_blocks = vec![
522 include_str!("../../../test_data/alonzo1.block"),
523 include_str!("../../../test_data/alonzo2.block"),
524 include_str!("../../../test_data/alonzo3.block"),
525 include_str!("../../../test_data/alonzo4.block"),
526 include_str!("../../../test_data/alonzo5.block"),
527 include_str!("../../../test_data/alonzo6.block"),
528 include_str!("../../../test_data/alonzo7.block"),
529 include_str!("../../../test_data/alonzo8.block"),
530 include_str!("../../../test_data/alonzo10.block"),
533 include_str!("../../../test_data/alonzo11.block"),
535 include_str!("../../../test_data/alonzo12.block"),
538 include_str!("../../../test_data/alonzo13.block"),
540 include_str!("../../../test_data/alonzo14.block"),
543 include_str!("../../../test_data/alonzo15.block"),
545 include_str!("../../../test_data/alonzo16.block"),
547 include_str!("../../../test_data/alonzo17.block"),
549 include_str!("../../../test_data/alonzo18.block"),
551 include_str!("../../../test_data/alonzo18.block"),
553 include_str!("../../../test_data/alonzo19.block"),
555 include_str!("../../../test_data/alonzo20.block"),
557 include_str!("../../../test_data/alonzo22.block"),
561 include_str!("../../../test_data/alonzo23.block"),
563 include_str!("../../../test_data/alonzo27.block"),
565 ];
566
567 for (idx, block_str) in test_blocks.iter().enumerate() {
568 println!("decoding test block {}", idx + 1);
569 let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
570
571 let block: BlockWrapper = minicbor::decode(&bytes[..])
572 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
573
574 let bytes2 = to_vec(block)
575 .unwrap_or_else(|_| panic!("error encoding block cbor for file {idx}"));
576
577 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
578 }
579 }
580
581 #[test]
582 fn header_isomorphic_decoding_encoding() {
583 let test_headers = [
584 include_str!("../../../test_data/alonzo26.header"),
586 ];
587
588 for (idx, header_str) in test_headers.iter().enumerate() {
589 println!("decoding test header {}", idx + 1);
590 let bytes = hex::decode(header_str).unwrap_or_else(|_| panic!("bad header file {idx}"));
591
592 let header: Header = minicbor::decode(&bytes[..])
593 .unwrap_or_else(|_| panic!("error decoding cbor for file {idx}"));
594
595 let bytes2 = to_vec(header)
596 .unwrap_or_else(|_| panic!("error encoding header cbor for file {idx}"));
597
598 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
599 }
600 }
601
602 #[test]
603 fn plutus_data_isomorphic_decoding_encoding() {
604 let datas = [
605 "d87980",
607 "a201d87980029f000102ff",
609 "9f000102ff",
611 "d87e9fa201d87980029f000102ffd87e9fa3a201d87980029f000102ffd87a809f000102ffa201d87980029f000102ff809f01ffd87980d8799f0001ffffff",
613 "d87e9f809f01ffa0a201d8798002d87b9f02ffff",
615 "58206969696969696969696969696969696969696969696969696969696969696969",
617 "5f58406969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696943696969ff",
619 "40",
621 ];
622 for data_hex in datas {
623 let data_bytes = hex::decode(data_hex).unwrap();
624 let data = PlutusData::decode_fragment(&data_bytes).unwrap();
625 assert_eq!(data.encode_fragment().unwrap(), data_bytes);
626 }
627 }
628}