amaru_kernel/cardano/
auxiliary_data.rs1use crate::{Hash, Hasher, KeyValuePairs, MemoizedNativeScript, Metadatum, NULL_HASH32, PlutusScript, cbor};
16
17#[derive(Debug, Clone, PartialEq, Eq, cbor::Encode, serde::Serialize, serde::Deserialize)]
18#[cbor(map)]
19pub struct AuxiliaryData {
20 #[cbor(skip)]
21 hash: Hash<{ AuxiliaryData::HASH_SIZE }>,
22
23 #[n(0)]
24 metadata: KeyValuePairs<u64, Metadatum>,
25
26 #[n(1)]
27 native_scripts: Vec<MemoizedNativeScript>,
28
29 #[n(2)]
30 plutus_v1_scripts: Vec<PlutusScript<1>>,
31
32 #[n(3)]
33 plutus_v2_scripts: Vec<PlutusScript<2>>,
34
35 #[n(4)]
36 plutus_v3_scripts: Vec<PlutusScript<3>>,
37}
38
39impl AuxiliaryData {
40 pub const HASH_SIZE: usize = 32;
42
43 pub fn hash(&self) -> Hash<{ Self::HASH_SIZE }> {
45 self.hash
46 }
47}
48
49impl Default for AuxiliaryData {
50 fn default() -> Self {
51 Self {
52 hash: NULL_HASH32,
53 metadata: KeyValuePairs::default(),
54 native_scripts: Vec::default(),
55 plutus_v1_scripts: Vec::default(),
56 plutus_v2_scripts: Vec::default(),
57 plutus_v3_scripts: Vec::default(),
58 }
59 }
60}
61
62impl<'b, C> cbor::Decode<'b, C> for AuxiliaryData {
88 fn decode(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
94 use cbor::data::Type::*;
95
96 let original_bytes = d.input();
97
98 let start_position = d.position();
99
100 #[allow(clippy::wildcard_enum_match_arm)]
101 let aux_data = match d.datatype()? {
102 Map | MapIndef => Self::decode_shelley(d, ctx),
103 Array | ArrayIndef => Self::decode_allegra(d, ctx),
104 Tag => Self::decode_alonzo(d, ctx),
105 any => Err(cbor::decode::Error::message(format!("unexpected type {any} when decoding auxiliary data"))),
106 }?;
107
108 let end_position = d.position();
109
110 Ok(Self { hash: Hasher::<256>::hash(&original_bytes[start_position..end_position]), ..aux_data })
111 }
112}
113
114impl AuxiliaryData {
119 fn decode_shelley<'b, C>(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
123 let metadata = d.decode_with(ctx)?;
124 Ok(Self { metadata, ..Self::default() })
125 }
126
127 fn decode_allegra<'b, C>(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
131 cbor::heterogeneous_array(d, |d, assert_len| {
132 assert_len(2)?;
133 let metadata = d.decode_with(ctx)?;
134 let native_scripts = d.decode_with(ctx)?;
135 Ok(Self { metadata, native_scripts, ..Self::default() })
136 })
137 }
138
139 fn decode_alonzo<'b, C>(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
143 if d.tag()? != cbor::TAG_MAP_259 {
144 return Err(cbor::decode::Error::tag_mismatch(cbor::TAG_MAP_259));
145 }
146
147 let mut st = Self::default();
148
149 cbor::heterogeneous_map(
150 d,
151 &mut st,
152 |d| d.u64(),
153 |d, st, k| {
154 match k {
155 0 => st.metadata = d.decode_with(ctx)?,
156 1 => st.native_scripts = d.decode_with(ctx)?,
157 2 => st.plutus_v1_scripts = d.decode_with(ctx)?,
158 3 => st.plutus_v2_scripts = d.decode_with(ctx)?,
159 4 => st.plutus_v3_scripts = d.decode_with(ctx)?,
160 _ => {
161 return Err(cbor::decode::Error::message(format!(
162 "unexpected field key {k} in auxiliary data"
163 ))
164 .at(d.position()));
165 }
166 };
167
168 Ok(())
169 },
170 )?;
171
172 Ok(st)
173 }
174}