amaru_kernel/cardano/memoized/
script.rs1use pallas_codec::utils::CborWrap;
16use pallas_primitives::{
17 KeepRaw,
18 conway::{NativeScript, PseudoScript},
19};
20use serde::ser::SerializeStruct;
21
22use crate::{
23 Bytes, MemoizedNativeScript, PlutusScript, cbor,
24 cbor::{bytes::ByteSlice, data::IanaTag},
25};
26
27pub type MemoizedScript = PseudoScript<MemoizedNativeScript>;
28
29pub fn serialize_memoized_script<S: serde::ser::Serializer>(
30 script: &MemoizedScript,
31 serializer: S,
32) -> Result<S::Ok, S::Error> {
33 let mut s = serializer.serialize_struct("MemoizedScript", 1)?;
34 match script {
35 MemoizedScript::NativeScript(native) => {
39 s.serialize_field("NativeScript", &hex::encode(native.original_bytes()))?;
40 }
41 MemoizedScript::PlutusV1Script(plutus) => {
42 s.serialize_field("PlutusV1Script", &hex::encode(plutus.as_ref()))?;
43 }
44 MemoizedScript::PlutusV2Script(plutus) => {
45 s.serialize_field("PlutusV2Script", &hex::encode(plutus.as_ref()))?;
46 }
47 MemoizedScript::PlutusV3Script(plutus) => {
48 s.serialize_field("PlutusV3Script", &hex::encode(plutus.as_ref()))?;
49 }
50 }
51 s.end()
52}
53
54pub fn script_original_bytes(script: &MemoizedScript) -> &[u8] {
55 match script {
56 MemoizedScript::NativeScript(native) => native.original_bytes(),
57 MemoizedScript::PlutusV1Script(plutus) => plutus.as_ref(),
58 MemoizedScript::PlutusV2Script(plutus) => plutus.as_ref(),
59 MemoizedScript::PlutusV3Script(plutus) => plutus.as_ref(),
60 }
61}
62
63pub fn decode_script<C>(d: &mut cbor::Decoder<'_>, ctx: &mut C) -> Result<MemoizedScript, cbor::decode::Error> {
64 let tag = d.tag()?;
65 if tag != IanaTag::Cbor.tag() {
66 return Err(cbor::decode::Error::message(format!(
67 "unexpected tag for script: expected {}, got {}",
68 IanaTag::Cbor.tag(),
69 tag
70 )));
71 }
72
73 let script: PseudoScript<MemoizedNativeScript> = cbor::Decoder::new(d.bytes()?)
74 .decode_with(ctx)
75 .map_err(|e| cbor::decode::Error::message(format!("failed to decode script: {e}")))?;
76
77 Ok(match script {
78 PseudoScript::NativeScript(n) => MemoizedScript::NativeScript(n),
79 PseudoScript::PlutusV1Script(s) => MemoizedScript::PlutusV1Script(s),
80 PseudoScript::PlutusV2Script(s) => MemoizedScript::PlutusV2Script(s),
81 PseudoScript::PlutusV3Script(s) => MemoizedScript::PlutusV3Script(s),
82 })
83}
84
85pub fn encode_script<W: cbor::encode::Write>(
86 script: &MemoizedScript,
87 e: &mut cbor::Encoder<W>,
88) -> Result<(), cbor::encode::Error<W::Error>> {
89 e.tag(IanaTag::Cbor)?;
90
91 let buffer = match script {
92 MemoizedScript::NativeScript(native) => {
93 let mut bytes = vec![
94 130, 0, ];
97 bytes.extend_from_slice(native.original_bytes());
98 bytes
99 }
100 MemoizedScript::PlutusV1Script(plutus) => {
101 #[expect(clippy::unwrap_used)] cbor::to_vec((1, Into::<&ByteSlice>::into(plutus.as_ref()))).unwrap()
103 }
104 MemoizedScript::PlutusV2Script(plutus) => {
105 #[expect(clippy::unwrap_used)] cbor::to_vec((2, Into::<&ByteSlice>::into(plutus.as_ref()))).unwrap()
107 }
108 MemoizedScript::PlutusV3Script(plutus) => {
109 #[expect(clippy::unwrap_used)] cbor::to_vec((3, Into::<&ByteSlice>::into(plutus.as_ref()))).unwrap()
111 }
112 };
113
114 e.bytes(&buffer)?;
115
116 Ok(())
117}
118
119pub fn from_minted_script(wrapper: CborWrap<PseudoScript<KeepRaw<'_, NativeScript>>>) -> MemoizedScript {
120 match wrapper.0 {
121 PseudoScript::NativeScript(script) => MemoizedScript::NativeScript(MemoizedNativeScript::from(script)),
122 PseudoScript::PlutusV1Script(script) => MemoizedScript::PlutusV1Script(script),
123 PseudoScript::PlutusV2Script(script) => MemoizedScript::PlutusV2Script(script),
124 PseudoScript::PlutusV3Script(script) => MemoizedScript::PlutusV3Script(script),
125 }
126}
127
128impl TryFrom<PlaceholderScript> for MemoizedScript {
129 type Error = String;
130
131 fn try_from(placeholder: PlaceholderScript) -> Result<Self, Self::Error> {
132 Ok(match placeholder {
133 PlaceholderScript::NativeScript(bytes) => {
134 MemoizedScript::NativeScript(MemoizedNativeScript::try_from(bytes)?)
135 }
136 PlaceholderScript::PlutusV1(bytes) => MemoizedScript::PlutusV1Script(PlutusScript(bytes)),
139 PlaceholderScript::PlutusV2(bytes) => MemoizedScript::PlutusV2Script(PlutusScript(bytes)),
140 PlaceholderScript::PlutusV3(bytes) => MemoizedScript::PlutusV3Script(PlutusScript(bytes)),
141 })
142 }
143}
144
145#[derive(serde::Deserialize)]
148pub(crate) enum PlaceholderScript {
149 NativeScript(Bytes),
150 PlutusV1(Bytes),
151 PlutusV2(Bytes),
152 PlutusV3(Bytes),
153}