zebra_chain/transparent/
script.rs
1use std::{fmt, io};
4
5use hex::{FromHex, FromHexError, ToHex};
6
7use crate::serialization::{
8 zcash_serialize_bytes, SerializationError, ZcashDeserialize, ZcashSerialize,
9};
10
11#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
13#[cfg_attr(
14 any(test, feature = "proptest-impl"),
15 derive(proptest_derive::Arbitrary)
16)]
17pub struct Script(
18 #[serde(with = "hex")]
23 Vec<u8>,
24);
25
26impl Script {
27 pub fn new(raw_bytes: &[u8]) -> Self {
30 Script(raw_bytes.to_vec())
31 }
32
33 pub fn as_raw_bytes(&self) -> &[u8] {
41 &self.0
42 }
43}
44
45impl fmt::Display for Script {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 f.write_str(&self.encode_hex::<String>())
48 }
49}
50
51impl fmt::Debug for Script {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 f.debug_tuple("Script")
54 .field(&hex::encode(&self.0))
55 .finish()
56 }
57}
58
59impl ToHex for &Script {
60 fn encode_hex<T: FromIterator<char>>(&self) -> T {
61 self.as_raw_bytes().encode_hex()
62 }
63
64 fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
65 self.as_raw_bytes().encode_hex_upper()
66 }
67}
68
69impl ToHex for Script {
70 fn encode_hex<T: FromIterator<char>>(&self) -> T {
71 (&self).encode_hex()
72 }
73
74 fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
75 (&self).encode_hex_upper()
76 }
77}
78
79impl FromHex for Script {
80 type Error = FromHexError;
81
82 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
83 let bytes = Vec::from_hex(hex)?;
84 Ok(Script::new(&bytes))
85 }
86}
87
88impl ZcashSerialize for Script {
89 fn zcash_serialize<W: io::Write>(&self, writer: W) -> Result<(), io::Error> {
90 zcash_serialize_bytes(&self.0, writer)
91 }
92}
93
94impl ZcashDeserialize for Script {
95 fn zcash_deserialize<R: io::Read>(reader: R) -> Result<Self, SerializationError> {
96 Vec::zcash_deserialize(reader).map(Script)
97 }
98}
99
100#[cfg(test)]
101mod proptests {
102 use std::io::Cursor;
103
104 use proptest::prelude::*;
105
106 use super::*;
107
108 proptest! {
109 #[test]
110 fn script_roundtrip(script in any::<Script>()) {
111 let _init_guard = zebra_test::init();
112
113 let mut bytes = Cursor::new(Vec::new());
114 script.zcash_serialize(&mut bytes)?;
115
116 bytes.set_position(0);
117 let other_script = Script::zcash_deserialize(&mut bytes)?;
118
119 prop_assert_eq![script, other_script];
120 }
121 }
122}