1use serde::{Deserialize, Serialize};
6
7use pallas_codec::{
8 minicbor::{self, Decode, Encode},
9 utils::{Bytes, CborWrap, KeepRaw, Nullable},
10};
11use pallas_crypto::hash::{Hash, Hasher};
12
13pub use pallas_codec::codec_by_datatype;
14
15pub use crate::{
16 AddrKeyhash, AssetName, DatumHash, DnsName, Epoch, ExUnitPrices, ExUnits, GenesisDelegateHash,
17 Genesishash, IPv4, IPv6, Metadata, Metadatum, MetadatumLabel, NetworkId, Nonce, NonceVariant,
18 PlutusScript, PolicyId, PoolKeyhash, PoolMetadata, PoolMetadataHash, Port, PositiveInterval,
19 ProtocolVersion, RationalNumber, Relay, ScriptHash, StakeCredential, TransactionIndex,
20 TransactionInput, UnitInterval, VrfCert, VrfKeyhash, plutus_data::*,
21};
22
23use crate::BTreeMap;
24
25#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
26pub struct HeaderBody {
27 #[n(0)]
28 pub block_number: u64,
29
30 #[n(1)]
31 pub slot: u64,
32
33 #[n(2)]
34 pub prev_hash: Option<Hash<32>>,
35
36 #[n(3)]
37 pub issuer_vkey: Bytes,
38
39 #[n(4)]
40 pub vrf_vkey: Bytes,
41
42 #[n(5)]
43 pub vrf_result: VrfCert,
44
45 #[n(6)]
46 pub block_body_size: u64,
47
48 #[n(7)]
49 pub block_body_hash: Hash<32>,
50
51 #[n(8)]
52 pub operational_cert: OperationalCert,
53
54 #[n(9)]
55 pub protocol_version: ProtocolVersion,
56}
57
58#[derive(Serialize, Deserialize, Encode, Decode, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
59pub struct OperationalCert {
60 #[n(0)]
61 pub operational_cert_hot_vkey: Bytes,
62
63 #[n(1)]
64 pub operational_cert_sequence_number: u64,
65
66 #[n(2)]
67 pub operational_cert_kes_period: u64,
68
69 #[n(3)]
70 pub operational_cert_sigma: Bytes,
71}
72
73#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
74pub struct Header {
75 #[n(0)]
76 pub header_body: HeaderBody,
77
78 #[n(1)]
79 pub body_signature: Bytes,
80}
81
82#[deprecated(since = "1.0.0-alpha", note = "use `KeepRaw<'_, Header>` instead")]
83pub type MintedHeader<'a> = KeepRaw<'a, Header>;
84
85pub use crate::alonzo::Multiasset;
86
87pub use crate::alonzo::Mint;
88
89pub use crate::alonzo::Coin;
90
91pub use crate::alonzo::Value;
92
93pub use crate::alonzo::TransactionOutput as LegacyTransactionOutput;
94
95pub use crate::alonzo::InstantaneousRewardSource;
96
97pub use crate::alonzo::InstantaneousRewardTarget;
98
99pub use crate::alonzo::MoveInstantaneousReward;
100
101pub use crate::alonzo::RewardAccount;
102
103pub use crate::alonzo::Withdrawals;
104
105pub use crate::alonzo::RequiredSigners;
106
107pub use crate::alonzo::Certificate;
108
109#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
110#[cbor(index_only)]
111pub enum Language {
112 #[n(0)]
113 PlutusV1,
114
115 #[n(1)]
116 PlutusV2,
117}
118
119#[deprecated(since = "0.31.0", note = "use `CostModels` instead")]
120pub type CostMdls = CostModels;
121
122pub use crate::alonzo::CostModel;
123
124#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
125#[cbor(map)]
126pub struct CostModels {
127 #[n(0)]
128 pub plutus_v1: Option<CostModel>,
129
130 #[n(1)]
131 pub plutus_v2: Option<CostModel>,
132}
133
134#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
135#[cbor(map)]
136pub struct ProtocolParamUpdate {
137 #[n(0)]
138 pub minfee_a: Option<u32>,
139 #[n(1)]
140 pub minfee_b: Option<u32>,
141 #[n(2)]
142 pub max_block_body_size: Option<u32>,
143 #[n(3)]
144 pub max_transaction_size: Option<u32>,
145 #[n(4)]
146 pub max_block_header_size: Option<u32>,
147 #[n(5)]
148 pub key_deposit: Option<Coin>,
149 #[n(6)]
150 pub pool_deposit: Option<Coin>,
151 #[n(7)]
152 pub maximum_epoch: Option<Epoch>,
153 #[n(8)]
154 pub desired_number_of_stake_pools: Option<u32>,
155 #[n(9)]
156 pub pool_pledge_influence: Option<RationalNumber>,
157 #[n(10)]
158 pub expansion_rate: Option<UnitInterval>,
159 #[n(11)]
160 pub treasury_growth_rate: Option<UnitInterval>,
161
162 #[n(14)]
163 pub protocol_version: Option<ProtocolVersion>,
164 #[n(16)]
165 pub min_pool_cost: Option<Coin>,
166 #[n(17)]
167 pub ada_per_utxo_byte: Option<Coin>,
168 #[n(18)]
169 pub cost_models_for_script_languages: Option<CostModels>,
170 #[n(19)]
171 pub execution_costs: Option<ExUnitPrices>,
172 #[n(20)]
173 pub max_tx_ex_units: Option<ExUnits>,
174 #[n(21)]
175 pub max_block_ex_units: Option<ExUnits>,
176 #[n(22)]
177 pub max_value_size: Option<u32>,
178 #[n(23)]
179 pub collateral_percentage: Option<u32>,
180 #[n(24)]
181 pub max_collateral_inputs: Option<u32>,
182}
183
184#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone)]
185pub struct Update {
186 #[n(0)]
187 pub proposed_protocol_parameter_updates: BTreeMap<Genesishash, ProtocolParamUpdate>,
188
189 #[n(1)]
190 pub epoch: Epoch,
191}
192
193#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Clone)]
194#[cbor(map)]
195pub struct TransactionBody<'b> {
196 #[n(0)]
197 pub inputs: Vec<TransactionInput>,
198
199 #[b(1)]
200 pub outputs: Vec<KeepRaw<'b, TransactionOutput<'b>>>,
201
202 #[n(2)]
203 pub fee: u64,
204
205 #[n(3)]
206 pub ttl: Option<u64>,
207
208 #[n(4)]
209 pub certificates: Option<Vec<Certificate>>,
210
211 #[n(5)]
212 pub withdrawals: Option<BTreeMap<RewardAccount, Coin>>,
213
214 #[n(6)]
215 pub update: Option<Update>,
216
217 #[n(7)]
218 pub auxiliary_data_hash: Option<Bytes>,
219
220 #[n(8)]
221 pub validity_interval_start: Option<u64>,
222
223 #[n(9)]
224 pub mint: Option<Multiasset<i64>>,
225
226 #[n(11)]
227 pub script_data_hash: Option<Hash<32>>,
228
229 #[n(13)]
230 pub collateral: Option<Vec<TransactionInput>>,
231
232 #[n(14)]
233 pub required_signers: Option<Vec<AddrKeyhash>>,
234
235 #[n(15)]
236 pub network_id: Option<NetworkId>,
237
238 #[n(16)]
239 pub collateral_return: Option<KeepRaw<'b, TransactionOutput<'b>>>,
240
241 #[n(17)]
242 pub total_collateral: Option<Coin>,
243
244 #[n(18)]
245 pub reference_inputs: Option<Vec<TransactionInput>>,
246}
247
248#[deprecated(since = "1.0.0-alpha", note = "use `TransactionBody` instead")]
249pub type MintedTransactionBody<'a> = TransactionBody<'a>;
250
251pub enum VrfDerivation {
252 Leader,
253 Nonce,
254}
255
256pub fn derive_tagged_vrf_output(
257 block_vrf_output_bytes: &[u8],
258 derivation: VrfDerivation,
259) -> Vec<u8> {
260 let mut tagged_vrf: Vec<u8> = match derivation {
261 VrfDerivation::Leader => vec![0x4C_u8], VrfDerivation::Nonce => vec![0x4E_u8], };
264
265 tagged_vrf.extend(block_vrf_output_bytes);
266 Hasher::<256>::hash(&tagged_vrf).to_vec()
267}
268
269impl HeaderBody {
270 pub fn leader_vrf_output(&self) -> Vec<u8> {
271 derive_tagged_vrf_output(&self.vrf_result.0, VrfDerivation::Leader)
272 }
273
274 pub fn nonce_vrf_output(&self) -> Vec<u8> {
275 derive_tagged_vrf_output(&self.vrf_result.0, VrfDerivation::Nonce)
276 }
277}
278
279#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
280pub enum GenTransactionOutput<'b, T> {
281 Legacy(KeepRaw<'b, LegacyTransactionOutput>),
282 PostAlonzo(KeepRaw<'b, T>),
283}
284
285codec_by_datatype! {
287 TransactionOutput<'b>,
288 Array | ArrayIndef => Legacy,
289 Map | MapIndef => PostAlonzo,
290 ()
291}
292
293pub type TransactionOutput<'b> = GenTransactionOutput<'b, PostAlonzoTransactionOutput<'b>>;
294
295#[deprecated(since = "1.0.0-alpha", note = "use `TransactionOutput` instead")]
296pub type MintedTransactionOutput<'b> = TransactionOutput<'b>;
297
298#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
299#[cbor(map)]
300pub struct GenPostAlonzoTransactionOutput<'b, V, S> {
301 #[n(0)]
302 pub address: Bytes,
303
304 #[n(1)]
305 pub value: V,
306
307 #[b(2)]
308 pub datum_option: Option<KeepRaw<'b, DatumOption<'b>>>,
309
310 #[n(3)]
311 pub script_ref: Option<CborWrap<S>>,
312}
313
314pub type PostAlonzoTransactionOutput<'b> = GenPostAlonzoTransactionOutput<'b, Value, ScriptRef<'b>>;
315
316#[deprecated(
317 since = "1.0.0-alpha",
318 note = "use `PostAlonzoTransactionOutput` instead"
319)]
320pub type MintedPostAlonzoTransactionOutput<'b> = PostAlonzoTransactionOutput<'b>;
321
322pub use crate::alonzo::VKeyWitness;
323
324pub use crate::alonzo::NativeScript;
325
326pub use crate::alonzo::RedeemerTag;
327
328pub use crate::alonzo::Redeemer;
329
330pub use crate::alonzo::BootstrapWitness;
331
332#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
333#[cbor(map)]
334pub struct WitnessSet<'b> {
335 #[n(0)]
336 pub vkeywitness: Option<Vec<VKeyWitness>>,
337
338 #[n(1)]
339 pub native_script: Option<Vec<KeepRaw<'b, NativeScript>>>,
340
341 #[n(2)]
342 pub bootstrap_witness: Option<Vec<BootstrapWitness>>,
343
344 #[n(3)]
345 pub plutus_v1_script: Option<Vec<PlutusScript<1>>>,
346
347 #[b(4)]
348 pub plutus_data: Option<Vec<KeepRaw<'b, PlutusData>>>,
349
350 #[n(5)]
351 pub redeemer: Option<Vec<Redeemer>>,
352
353 #[n(6)]
354 pub plutus_v2_script: Option<Vec<PlutusScript<2>>>,
355}
356
357#[deprecated(since = "1.0.0-alpha", note = "use `WitnessSet` instead")]
358pub type MintedWitnessSet<'b> = WitnessSet<'b>;
359
360#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
361#[cbor(map)]
362pub struct PostAlonzoAuxiliaryData {
363 #[n(0)]
364 pub metadata: Option<Metadata>,
365
366 #[n(1)]
367 pub native_scripts: Option<Vec<NativeScript>>,
368
369 #[n(2)]
370 pub plutus_v1_scripts: Option<Vec<PlutusScript<1>>>,
371
372 #[n(3)]
373 pub plutus_v2_scripts: Option<Vec<PlutusScript<2>>>,
374}
375
376#[derive(Encode, Decode, Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
378#[cbor(flat)]
379pub enum DatumOption<'b> {
380 #[n(0)]
381 Hash(#[n(0)] DatumHash),
382 #[n(1)]
383 Data(#[b(0)] CborWrap<KeepRaw<'b, PlutusData>>),
384}
385
386#[deprecated(since = "1.0.0-alpha", note = "use `DatumOption` instead")]
387pub type MintedDatumOption<'b> = DatumOption<'b>;
388
389#[deprecated(since = "0.31.0", note = "use `PlutusScript<1>` instead")]
390pub type PlutusV1Script = PlutusScript<1>;
391
392#[deprecated(since = "0.31.0", note = "use `PlutusScript<2>` instead")]
393pub type PlutusV2Script = PlutusScript<2>;
394
395#[derive(Encode, Decode, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
397#[cbor(flat)]
398pub enum ScriptRef<'b> {
399 #[n(0)]
400 NativeScript(#[b(0)] KeepRaw<'b, NativeScript>),
401 #[n(1)]
402 PlutusV1Script(#[n(0)] PlutusScript<1>),
403 #[n(2)]
404 PlutusV2Script(#[n(0)] PlutusScript<2>),
405}
406
407#[deprecated(since = "1.0.0-alpha", note = "use `ScriptRef` instead")]
408pub type MintedScriptRef<'b> = ScriptRef<'b>;
409
410pub use crate::alonzo::AuxiliaryData;
411
412#[derive(Serialize, Encode, Decode, Debug, PartialEq, Clone)]
418pub struct Block<'b> {
419 #[n(0)]
420 pub header: KeepRaw<'b, Header>,
421
422 #[b(1)]
423 pub transaction_bodies: Vec<KeepRaw<'b, TransactionBody<'b>>>,
424
425 #[n(2)]
426 pub transaction_witness_sets: Vec<KeepRaw<'b, WitnessSet<'b>>>,
427
428 #[n(3)]
429 pub auxiliary_data_set: BTreeMap<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
430
431 #[n(4)]
432 pub invalid_transactions: Option<Vec<TransactionIndex>>,
433}
434
435#[deprecated(since = "1.0.0-alpha", note = "use `Block` instead")]
436pub type MintedBlock<'b> = Block<'b>;
437
438#[derive(Clone, Serialize, Deserialize, Encode, Decode, Debug)]
439pub struct Tx<'b> {
440 #[b(0)]
441 pub transaction_body: KeepRaw<'b, TransactionBody<'b>>,
442
443 #[n(1)]
444 pub transaction_witness_set: KeepRaw<'b, WitnessSet<'b>>,
445
446 #[n(2)]
447 pub success: bool,
448
449 #[n(3)]
450 pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
451}
452
453#[deprecated(since = "1.0.0-alpha", note = "use `Tx` instead")]
454pub type MintedTx<'b> = Tx<'b>;
455
456#[cfg(test)]
457mod tests {
458 use pallas_codec::minicbor;
459
460 use super::{Block, TransactionOutput};
461 use crate::Fragment;
462
463 type BlockWrapper<'b> = (u16, Block<'b>);
464
465 #[test]
466 fn block_isomorphic_decoding_encoding() {
467 let test_blocks = [
468 include_str!("../../../test_data/babbage1.block"),
469 include_str!("../../../test_data/babbage2.block"),
470 include_str!("../../../test_data/babbage3.block"),
471 include_str!("../../../test_data/babbage4.block"),
473 include_str!("../../../test_data/babbage5.block"),
475 include_str!("../../../test_data/babbage6.block"),
477 include_str!("../../../test_data/babbage7.block"),
479 include_str!("../../../test_data/babbage8.block"),
481 include_str!("../../../test_data/babbage10.block"),
485 ];
486
487 for (idx, block_str) in test_blocks.iter().enumerate() {
488 println!("decoding test block {}", idx + 1);
489 let bytes = hex::decode(block_str).unwrap_or_else(|_| panic!("bad block file {idx}"));
490
491 let block: BlockWrapper = minicbor::decode(&bytes[..])
492 .unwrap_or_else(|e| panic!("error decoding cbor for file {idx}: {e:?}"));
493
494 let bytes2 = minicbor::to_vec(block)
495 .unwrap_or_else(|e| panic!("error encoding block cbor for file {idx}: {e:?}"));
496
497 assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
498 }
499 }
500
501 #[test]
502 fn fragments_decoding() {
503 let hex = include_str!("../../../test_data/babbage1.fr");
505 let bytes = hex::decode(hex).unwrap();
506 let outputs = Vec::<TransactionOutput>::decode_fragment(&bytes).unwrap();
507
508 dbg!(outputs);
509
510 }
512}