tx_bakery/utils/
script.rs

1//! Plutus Script management
2
3use anyhow::anyhow;
4use plutus_ledger_api::{
5    csl::{csl_to_pla::ToPLA, lib as csl},
6    v3::{
7        script::{MintingPolicyHash, ScriptHash, ValidatorHash},
8        transaction::TransactionInput,
9    },
10};
11
12use crate::error::{Error, Result};
13
14#[derive(Clone, Debug)]
15pub enum Script {
16    PlutusScript(csl::PlutusScript),
17    NativeScript(csl::NativeScript),
18}
19
20/// Plutus Script
21#[derive(Clone, Debug)]
22pub enum ScriptOrRef {
23    /// Script will be used from a reference input
24    RefScript(TransactionInput, csl::PlutusScript),
25    /// Script will be added as script witness
26    PlutusScript(csl::PlutusScript),
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub enum PlutusVersion {
31    V1,
32    V2,
33    V3,
34}
35
36impl ScriptOrRef {
37    pub fn from_bytes(bytes: Vec<u8>, version: PlutusVersion) -> Result<Self> {
38        let mut serializer = cbor_event::se::Serializer::new_vec();
39        serializer.write_bytes(bytes).unwrap();
40        let script_bytes = serializer.finalize();
41
42        let script = match version {
43            PlutusVersion::V1 => csl::PlutusScript::from_bytes(script_bytes)
44                .map_err(|source| Error::ConversionError(anyhow!(source)))?,
45            PlutusVersion::V2 => csl::PlutusScript::from_bytes_v2(script_bytes)
46                .map_err(|source| Error::ConversionError(anyhow!(source)))?,
47            PlutusVersion::V3 => csl::PlutusScript::from_bytes_v3(script_bytes)
48                .map_err(|source| Error::ConversionError(anyhow!(source)))?,
49        };
50        Ok(ScriptOrRef::PlutusScript(script))
51    }
52
53    pub fn from_bytes_v1(bytes: Vec<u8>) -> Result<Self> {
54        Self::from_bytes(bytes, PlutusVersion::V1)
55    }
56
57    pub fn from_bytes_v2(bytes: Vec<u8>) -> Result<Self> {
58        Self::from_bytes(bytes, PlutusVersion::V2)
59    }
60
61    pub fn from_bytes_v3(bytes: Vec<u8>) -> Result<Self> {
62        Self::from_bytes(bytes, PlutusVersion::V3)
63    }
64
65    pub fn from_script(script: Script) -> Result<Self> {
66        match script {
67            Script::PlutusScript(script) => Ok(ScriptOrRef::PlutusScript(script)),
68            Script::NativeScript(_) => Err(Error::Unsupported(
69                "Native scripts are not supported yet.".to_string(),
70            )),
71        }
72    }
73
74    pub fn into_ref_script(self, tx_in: TransactionInput) -> Self {
75        match self {
76            ScriptOrRef::RefScript(_, _) => self,
77            ScriptOrRef::PlutusScript(script) => ScriptOrRef::RefScript(tx_in, script),
78        }
79    }
80
81    pub fn get_script(self) -> csl::PlutusScript {
82        match self {
83            ScriptOrRef::RefScript(_, script) => script,
84            ScriptOrRef::PlutusScript(script) => script,
85        }
86    }
87
88    pub fn get_script_hash(&self) -> ScriptHash {
89        match self {
90            ScriptOrRef::RefScript(_, script) => script.hash().to_pla(),
91            ScriptOrRef::PlutusScript(script) => script.hash().to_pla(),
92        }
93    }
94
95    pub fn get_script_size(&self) -> usize {
96        match self {
97            ScriptOrRef::RefScript(_, script) => script.bytes().len(),
98            ScriptOrRef::PlutusScript(script) => script.bytes().len(),
99        }
100    }
101
102    pub fn get_version(self) -> csl::Language {
103        match self {
104            ScriptOrRef::RefScript(_, script) => script.language_version(),
105            ScriptOrRef::PlutusScript(script) => script.language_version(),
106        }
107    }
108
109    pub fn as_validator(self) -> (ValidatorHash, ScriptOrRef) {
110        let (sh, s) = self.with_script_hash();
111        (ValidatorHash(sh), s)
112    }
113
114    pub fn as_minting_policy(self) -> (MintingPolicyHash, ScriptOrRef) {
115        let (sh, s) = self.with_script_hash();
116        (MintingPolicyHash(sh), s)
117    }
118
119    pub fn with_script_hash(self) -> (ScriptHash, ScriptOrRef) {
120        let script_hash = self.get_script_hash();
121
122        (script_hash, self)
123    }
124}