1use crate::error::{Result, ScriptSerializeError};
2use crate::{encoding_utils::encode_int, ByteArray, Op, Opcode, Ops, TaggedOp};
3use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
5use std::borrow::Cow;
6use std::io::Read;
7use std::sync::Arc;
8
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct Script {
11 ops: Arc<[TaggedOp]>,
12}
13
14impl Ops for Script {
15 fn ops(&self) -> Cow<[TaggedOp]> {
16 self.ops.as_ref().into()
17 }
18}
19
20impl Script {
21 pub fn new(ops: impl Into<Arc<[TaggedOp]>>) -> Self {
22 Script { ops: ops.into() }
23 }
24
25 pub fn serialize(&self) -> Result<ByteArray> {
26 serialize_ops(self.ops.iter().map(|op| &op.op))
27 }
28}
29
30impl Script {
31 pub fn ops_arc(&self) -> &Arc<[TaggedOp]> {
32 &self.ops
33 }
34
35 pub fn to_script_code(&self, n_codesep: Option<usize>) -> Script {
36 let idx = if let Some(n_codesep) = n_codesep {
37 let mut n_codeseps_found = 0;
38 let mut codesep_idx = None;
39 for (idx, op) in self.ops.iter().enumerate() {
40 match op.op {
41 Op::Code(Opcode::OP_CODESEPARATOR) => {
42 if n_codesep == n_codeseps_found {
43 codesep_idx = Some(idx);
44 break;
45 }
46 n_codeseps_found += 1;
47 }
48 _ => continue,
49 }
50 }
51 codesep_idx.expect("Couldn't find OP_CODESEPARATOR")
52 } else {
53 0
54 };
55 Script::new(self.ops[idx..].to_vec())
56 }
57
58 pub fn to_script_code_first(&self) -> Script {
59 if let Some(code_separator_idx) = self
60 .ops
61 .iter()
62 .position(|op| op.op == Op::Code(Opcode::OP_CODESEPARATOR))
63 {
64 Script::new(self.ops[code_separator_idx + 1..].to_vec())
65 } else {
66 self.clone()
67 }
68 }
69}
70
71impl Default for Script {
72 fn default() -> Self {
73 Script { ops: Arc::new([]) }
74 }
75}
76
77#[derive(Clone, Copy)]
78enum PushPrefixTail {
79 NoTail,
80 PushedData,
81}
82
83fn serialize_push_prefix(
84 vec: &mut Vec<u8>,
85 bytes: &[u8],
86 is_minimal_push: bool,
87) -> Result<PushPrefixTail> {
88 use Opcode::*;
89 match bytes.len() {
90 0 if is_minimal_push => {
91 vec.push(OP_0 as u8);
92 return Ok(PushPrefixTail::NoTail);
93 }
94 0 if !is_minimal_push => {
95 vec.push(OP_PUSHDATA1 as u8);
96 vec.push(0);
97 }
98 1 if is_minimal_push => {
99 let value = bytes[0];
100 if value <= 16 {
101 vec.push(OP_1 as u8 - 1 + value);
102 return Ok(PushPrefixTail::NoTail);
103 } else if value == 0x81 {
104 vec.push(OP_1NEGATE as u8);
105 return Ok(PushPrefixTail::NoTail);
106 } else {
107 vec.push(1);
108 }
109 }
110 len @ 0x00..=0x4b => vec.push(len as u8),
111 len @ 0x4c..=0xff => {
112 vec.push(OP_PUSHDATA1 as u8);
113 vec.push(len as u8);
114 }
115 len @ 0x100..=0xffff => {
116 vec.push(OP_PUSHDATA2 as u8);
117 vec.write_u16::<LittleEndian>(len as u16).unwrap();
118 }
119 len @ 0x10000..=0xffff_ffff => {
120 vec.push(OP_PUSHDATA4 as u8);
121 vec.write_u32::<LittleEndian>(len as u32).unwrap();
122 }
123 _ => return ScriptSerializeError::PushTooLarge.into_err(),
124 }
125 Ok(PushPrefixTail::PushedData)
126}
127
128fn serialize_push_bytes(bytes: ByteArray, is_minimal_push: bool) -> Result<ByteArray> {
129 use PushPrefixTail::*;
130 let mut vec = Vec::new();
131 match serialize_push_prefix(&mut vec, &bytes, is_minimal_push)? {
132 NoTail => Ok(vec.into()),
133 PushedData => Ok(ByteArray::new_unnamed(vec).concat(bytes)),
134 }
135}
136
137pub fn serialize_op(op: &Op) -> Result<ByteArray> {
138 use Opcode::*;
139 match *op {
140 Op::Code(opcode) => Ok([opcode as u8].into()),
141 Op::Invalid(opcode) => Ok([opcode as u8].into()),
142 Op::PushBoolean(boolean) => Ok([if boolean { OP_1 as u8 } else { OP_0 as u8 }].into()),
143 Op::PushInteger(int) => Ok([match int {
144 -1 => OP_1NEGATE as u8,
145 0 => OP_0 as u8,
146 1..=16 => OP_1 as u8 + int as u8 - 1,
147 -0x8000_0000 => return ScriptSerializeError::InvalidInteger.into_err(),
148 _ => {
149 return serialize_push_bytes(encode_int(int).into(), false);
150 }
151 }]
152 .into()),
153 Op::PushByteArray {
154 ref array,
155 is_minimal,
156 } => serialize_push_bytes(array.clone(), is_minimal),
157 }
158}
159
160pub fn serialize_ops<'a>(ops: impl IntoIterator<Item = &'a Op>) -> Result<ByteArray> {
161 let mut byte_array: ByteArray = [].into();
162 for op in ops {
163 byte_array = byte_array.concat(serialize_op(op)?);
164 }
165 Ok(byte_array)
166}
167
168pub fn deserialize_ops(bytes: &[u8]) -> Result<Vec<Op>> {
169 use Opcode::*;
170 let mut i = 0;
171 let mut ops = Vec::new();
172 let mut cur = std::io::Cursor::new(bytes);
173 while i < bytes.len() {
174 let byte = cur.read_u8()?;
175 i += 1;
176 let push_len = match byte {
177 0 => {
178 ops.push(Op::Code(OP_0));
179 continue;
180 }
181 push_len @ 0x01..=0x4b => push_len as usize,
182 byte if byte == OP_PUSHDATA1 as u8 => {
183 i += 1;
184 cur.read_u8()? as usize
185 }
186 byte if byte == OP_PUSHDATA2 as u8 => {
187 i += 2;
188 cur.read_u16::<LittleEndian>()? as usize
189 }
190 byte if byte == OP_PUSHDATA4 as u8 => {
191 i += 4;
192 cur.read_u32::<LittleEndian>()? as usize
193 }
194 opcode => {
195 let opcode = num::FromPrimitive::from_u8(opcode)
196 .ok_or(())
197 .or_else(|()| ScriptSerializeError::UnknownOpcode.into_err())?;
198 ops.push(Op::Code(opcode));
199 continue;
200 }
201 };
202 let mut vec = vec![0; push_len];
203 cur.read_exact(&mut vec)?;
204 i += push_len;
205 let mut prefix = Vec::new();
206 serialize_push_prefix(&mut prefix, &vec, true)?;
207 let mut op: Op = ByteArray::new_unnamed(vec).into();
208 if prefix[0] == byte {
209 if let Op::PushByteArray { is_minimal, .. } = &mut op {
210 *is_minimal = false;
211 }
212 }
213 ops.push(op);
214 }
215 Ok(ops)
216}
217
218pub fn deserialize_ops_byte_array(byte_array: ByteArray) -> Result<Vec<Op>> {
219 use std::convert::TryInto;
220 use Opcode::*;
221 let mut ops = Vec::new();
222 let mut byte_array = Some(byte_array);
223 while byte_array.as_ref().map_or(false, |array| array.len() > 0) {
224 let (head, remainder) = byte_array.take().unwrap().split(1)?;
225 let byte = head[0];
226 let (push_len, remainder) = match byte {
227 0 => {
228 ops.push(Op::Code(OP_0));
229 byte_array = Some(remainder);
230 continue;
231 }
232 push_len @ 0x01..=0x4b => (push_len as usize, remainder),
233 byte if byte == OP_PUSHDATA1 as u8 => {
234 let (push_len, remainder) = remainder.split(1)?;
235 (push_len[0] as usize, remainder)
236 }
237 byte if byte == OP_PUSHDATA2 as u8 => {
238 let (push_len, remainder) = remainder.split(2)?;
239 (
240 u16::from_le_bytes(push_len.as_ref().try_into().unwrap()) as usize,
241 remainder,
242 )
243 }
244 byte if byte == OP_PUSHDATA4 as u8 => {
245 let (push_len, remainder) = remainder.split(4)?;
246 (
247 u32::from_le_bytes(push_len.as_ref().try_into().unwrap()) as usize,
248 remainder,
249 )
250 }
251 opcode => {
252 ops.push(
253 num::FromPrimitive::from_u8(opcode)
254 .map(Op::Code)
255 .unwrap_or(Op::Invalid(opcode)),
256 );
257 byte_array = Some(remainder);
258 continue;
259 }
260 };
261 let (pushed, remainder) = remainder.split(push_len)?;
262 let mut prefix = Vec::new();
263 serialize_push_prefix(&mut prefix, &pushed, true)?;
264 let mut op: Op = pushed.into();
265 if prefix[0] == byte {
266 if let Op::PushByteArray { is_minimal, .. } = &mut op {
267 *is_minimal = false;
268 }
269 }
270 ops.push(op);
271 byte_array = Some(remainder);
272 }
273 Ok(ops)
274}
275
276impl Serialize for Script {
277 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
278 use ser::Error;
279 serializer.serialize_bytes(
280 &serialize_ops(self.ops.iter().map(|op| &op.op))
281 .map_err(|err| S::Error::custom(err.to_string()))?,
282 )
283 }
284}
285
286struct ScriptVisitor;
287
288impl<'de> de::Visitor<'de> for ScriptVisitor {
289 type Value = Vec<TaggedOp>;
290 fn expecting(
291 &self,
292 fmt: &mut std::fmt::Formatter<'_>,
293 ) -> std::result::Result<(), std::fmt::Error> {
294 write!(fmt, "a byte array")
295 }
296
297 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> std::result::Result<Self::Value, E> {
298 let ops = deserialize_ops(v).map_err(|err| E::custom(err.to_string()))?;
299 Ok(ops.into_iter().map(TaggedOp::from_op).collect())
300 }
301}
302
303impl<'de, 'a> Deserialize<'de> for Script {
304 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
305 where
306 D: Deserializer<'de>,
307 {
308 Ok(Script::new(deserializer.deserialize_bytes(ScriptVisitor)?))
309 }
310}
311
312#[cfg(test)]
313mod tests {}