whisky_pallas/wrapper/witness_set/
native_script.rs1use std::str::FromStr;
2
3use pallas::{
4 crypto::hash::Hash,
5 ledger::{
6 primitives::{conway::NativeScript as PallasNativeScript, Fragment},
7 traverse::ComputeHash,
8 },
9};
10use whisky_common::WError;
11
12pub enum NativeScriptKind {
13 ScriptPubkey(String),
14 ScriptAll(Vec<NativeScriptKind>),
15 ScriptAny(Vec<NativeScriptKind>),
16 ScriptNOfK(u32, Vec<NativeScriptKind>),
17 InvalidBefore(u64),
18 InvalidHereafter(u64),
19}
20
21#[derive(Debug, PartialEq, Eq, Clone)]
22pub struct NativeScript {
23 pub inner: PallasNativeScript,
24}
25
26impl NativeScript {
27 pub fn new(native_script: NativeScriptKind) -> Result<Self, WError> {
28 let inner = Self::convert_native_script_kind_to_pallas(native_script)?;
29 Ok(NativeScript { inner })
30 }
31
32 pub fn new_from_hex(hex_str: &str) -> Result<Self, WError> {
33 let bytes = hex::decode(hex_str).map_err(|e| {
34 WError::new(
35 "WhiskyPallas - Creating native script from hex:",
36 &format!("Hex decode error: {}", e.to_string()),
37 )
38 })?;
39 let inner = PallasNativeScript::decode_fragment(&bytes).map_err(|e| {
40 WError::new(
41 "WhiskyPallas - Creating native script from hex:",
42 &format!("Fragment decode error: {}", e.to_string()),
43 )
44 })?;
45 Ok(NativeScript { inner })
46 }
47
48 fn convert_native_script_kind_to_pallas(
49 kind: NativeScriptKind,
50 ) -> Result<PallasNativeScript, WError> {
51 match kind {
52 NativeScriptKind::ScriptPubkey(key_hash) => {
53 let bytes = Hash::<28>::from_str(&key_hash).map_err(|e| {
54 WError::new(
55 "WhiskyPallas - Converting native script:",
56 &format!("Invalid key hash: {}", e),
57 )
58 })?;
59 Ok(PallasNativeScript::ScriptPubkey(bytes))
60 }
61 NativeScriptKind::ScriptAll(scripts) => {
62 let converted: Result<Vec<_>, WError> = scripts
63 .into_iter()
64 .map(Self::convert_native_script_kind_to_pallas)
65 .collect();
66 Ok(PallasNativeScript::ScriptAll(converted?))
67 }
68 NativeScriptKind::ScriptAny(scripts) => {
69 let converted: Result<Vec<_>, WError> = scripts
70 .into_iter()
71 .map(Self::convert_native_script_kind_to_pallas)
72 .collect();
73 Ok(PallasNativeScript::ScriptAny(converted?))
74 }
75 NativeScriptKind::ScriptNOfK(n, scripts) => {
76 let converted: Result<Vec<_>, WError> = scripts
77 .into_iter()
78 .map(Self::convert_native_script_kind_to_pallas)
79 .collect();
80 Ok(PallasNativeScript::ScriptNOfK(n, converted?))
81 }
82 NativeScriptKind::InvalidBefore(slot) => Ok(PallasNativeScript::InvalidBefore(slot)),
83 NativeScriptKind::InvalidHereafter(slot) => {
84 Ok(PallasNativeScript::InvalidHereafter(slot))
85 }
86 }
87 }
88
89 pub fn encode(&self) -> Result<String, WError> {
90 self.inner
91 .encode_fragment()
92 .map(|bytes| hex::encode(bytes))
93 .map_err(|_| {
94 WError::new(
95 "WhiskyPallas - Encoding native script:",
96 "Failed to encode fragment",
97 )
98 })
99 }
100
101 pub fn decode_bytes(bytes: &[u8]) -> Result<Self, WError> {
102 let inner = PallasNativeScript::decode_fragment(&bytes).map_err(|e| {
103 WError::new(
104 "WhiskyPallas - Decoding native script:",
105 &format!("Fragment decode error: {}", e.to_string()),
106 )
107 })?;
108 Ok(Self { inner })
109 }
110
111 pub fn hash(&self) -> String {
112 self.inner.compute_hash().to_string()
113 }
114}