Skip to main content

kaspa_txscript/
data_stack.rs

1use crate::{MAX_SCRIPT_ELEMENT_SIZE, TxScriptError};
2use core::fmt::Debug;
3use core::iter;
4use kaspa_hashes::Hash;
5use kaspa_txscript_errors::SerializationError;
6use smallvec::SmallVec;
7use std::cmp::Ordering;
8use std::num::TryFromIntError;
9use std::ops::{Deref, Index};
10
11#[derive(PartialEq, Eq, Debug, Default, PartialOrd, Ord)]
12pub(crate) struct SizedEncodeInt<const LEN: usize>(pub(crate) i64);
13
14impl<const LEN: usize> From<i64> for SizedEncodeInt<LEN> {
15    fn from(value: i64) -> Self {
16        SizedEncodeInt(value)
17    }
18}
19
20impl<const LEN: usize> From<i32> for SizedEncodeInt<LEN> {
21    fn from(value: i32) -> Self {
22        SizedEncodeInt(value as i64)
23    }
24}
25
26impl<const LEN: usize> TryFrom<SizedEncodeInt<LEN>> for i32 {
27    type Error = TryFromIntError;
28
29    fn try_from(value: SizedEncodeInt<LEN>) -> Result<Self, Self::Error> {
30        value.0.try_into()
31    }
32}
33
34impl<const LEN: usize> PartialEq<i64> for SizedEncodeInt<LEN> {
35    fn eq(&self, other: &i64) -> bool {
36        self.0 == *other
37    }
38}
39
40impl<const LEN: usize> PartialOrd<i64> for SizedEncodeInt<LEN> {
41    fn partial_cmp(&self, other: &i64) -> Option<Ordering> {
42        self.0.partial_cmp(other)
43    }
44}
45
46impl<const LEN: usize> Deref for SizedEncodeInt<LEN> {
47    type Target = i64;
48
49    fn deref(&self) -> &Self::Target {
50        &self.0
51    }
52}
53
54impl<const LEN: usize> From<SizedEncodeInt<LEN>> for i64 {
55    fn from(value: SizedEncodeInt<LEN>) -> Self {
56        value.0
57    }
58}
59
60#[inline]
61fn total_bytes(items: &[StackEntry]) -> usize {
62    items.iter().map(|item| item.len()).sum()
63}
64
65pub type StackEntry = SmallVec<[u8; 8]>;
66
67#[derive(Clone, Debug)]
68pub(crate) struct Stack {
69    inner: Vec<StackEntry>,
70    pushed_bytes: u64,
71}
72
73#[cfg(test)]
74impl PartialEq for Stack {
75    fn eq(&self, other: &Self) -> bool {
76        self.inner == other.inner
77    }
78}
79
80#[cfg(test)]
81impl Eq for Stack {}
82
83impl Deref for Stack {
84    type Target = Vec<StackEntry>;
85
86    fn deref(&self) -> &Self::Target {
87        &self.inner
88    }
89}
90
91impl Index<usize> for Stack {
92    type Output = StackEntry;
93
94    fn index(&self, index: usize) -> &Self::Output {
95        &self.inner[index]
96    }
97}
98
99#[cfg(test)]
100impl From<Vec<StackEntry>> for Stack {
101    fn from(inner: Vec<StackEntry>) -> Self {
102        Self { inner, pushed_bytes: 0 }
103    }
104}
105
106#[cfg(test)]
107impl From<Vec<Vec<u8>>> for Stack {
108    fn from(inner: Vec<Vec<u8>>) -> Self {
109        Self::from(inner.into_iter().map(SmallVec::from_vec).collect::<Vec<_>>())
110    }
111}
112
113impl From<Stack> for Vec<StackEntry> {
114    fn from(stack: Stack) -> Self {
115        stack.inner
116    }
117}
118
119pub(crate) trait OpcodeData<T> {
120    fn deserialize(&self) -> Result<T, TxScriptError>;
121    fn serialize(from: &T) -> Result<Self, SerializationError>
122    where
123        Self: Sized;
124}
125
126#[inline]
127pub fn serialize_i64(from: i64, size: Option<usize>) -> Result<StackEntry, SerializationError> {
128    let sign = from.signum();
129    let mut positive = from.unsigned_abs();
130    let mut last_saturated = false;
131    let mut number_vec = StackEntry::with_capacity(size.unwrap_or(8));
132    number_vec.extend(iter::from_fn(move || {
133        if positive == 0 {
134            if last_saturated {
135                last_saturated = false;
136                Some(0)
137            } else {
138                None
139            }
140        } else {
141            let value = positive & 0xff;
142            last_saturated = (value & 0x80) != 0;
143            positive >>= 8;
144            Some(value as u8)
145        }
146    }));
147
148    if let Some(size) = size {
149        if number_vec.len() > size {
150            return Err(SerializationError::NumberTooLong(from, size));
151        }
152        number_vec.resize(size, 0);
153    }
154
155    if sign == -1 {
156        match number_vec.last_mut() {
157            Some(num) => *num |= 0x80,
158            _ => unreachable!(),
159        }
160    }
161    Ok(number_vec)
162}
163
164pub fn deserialize_i64(v: &[u8]) -> Result<i64, TxScriptError> {
165    match v.len() {
166        l if l > size_of::<i64>() => {
167            // Numbers are not required to be minimally encoded, but they are still bounded in width.
168            Err(TxScriptError::NotMinimalData(format!("numeric value encoded as {v:x?} is longer than 8 bytes")))
169        }
170        0 => Ok(0),
171        _ => {
172            let msb = v[v.len() - 1];
173            let sign = 1 - 2 * ((msb >> 7) as i64);
174            let first_byte = (msb & 0x7f) as i64;
175            Ok(v[..v.len() - 1].iter().rev().map(|v| *v as i64).fold(first_byte, |accum, item| (accum << 8) + item) * sign)
176        }
177    }
178}
179
180impl OpcodeData<i64> for StackEntry {
181    #[inline]
182    fn deserialize(&self) -> Result<i64, TxScriptError> {
183        OpcodeData::<SizedEncodeInt<8>>::deserialize(self).map(i64::from)
184    }
185
186    #[inline]
187    fn serialize(from: &i64) -> Result<Self, SerializationError> {
188        OpcodeData::<SizedEncodeInt<8>>::serialize(&(*from).into())
189    }
190}
191
192impl OpcodeData<i32> for StackEntry {
193    #[inline]
194    fn deserialize(&self) -> Result<i32, TxScriptError> {
195        OpcodeData::<SizedEncodeInt<8>>::deserialize(self)
196            .and_then(|v| v.try_into().map_err(|e: TryFromIntError| TxScriptError::NumberTooBig(e.to_string())))
197    }
198
199    #[inline]
200    fn serialize(from: &i32) -> Result<Self, SerializationError> {
201        OpcodeData::<SizedEncodeInt<4>>::serialize(&(*from).into())
202    }
203}
204
205impl<const LEN: usize> OpcodeData<SizedEncodeInt<LEN>> for StackEntry {
206    #[inline]
207    fn deserialize(&self) -> Result<SizedEncodeInt<LEN>, TxScriptError> {
208        match self.len() > LEN {
209            true => Err(TxScriptError::NumberTooBig(format!(
210                "numeric value encoded as {:x?} is {} bytes which exceeds the max allowed of {}",
211                self,
212                self.len(),
213                LEN
214            ))),
215            false => deserialize_i64(self).map(SizedEncodeInt::<LEN>),
216        }
217    }
218
219    #[inline]
220    fn serialize(from: &SizedEncodeInt<LEN>) -> Result<Self, SerializationError> {
221        let bytes = serialize_i64(from.0, None)?;
222        if bytes.len() > LEN {
223            return Err(SerializationError::NumberTooLong(from.0, LEN));
224        }
225        Ok(bytes)
226    }
227}
228
229impl OpcodeData<bool> for StackEntry {
230    #[inline]
231    fn deserialize(&self) -> Result<bool, TxScriptError> {
232        if self.is_empty() {
233            Ok(false)
234        } else {
235            // Negative 0 is also considered false
236            Ok(self[self.len() - 1] & 0x7f != 0x0 || self[..self.len() - 1].iter().any(|&b| b != 0x0))
237        }
238    }
239
240    #[inline]
241    fn serialize(from: &bool) -> Result<Self, SerializationError> {
242        Ok(match from {
243            true => SmallVec::from_slice(&[1]),
244            false => SmallVec::new(),
245        })
246    }
247}
248
249#[cfg(test)]
250impl<T> OpcodeData<T> for Vec<u8>
251where
252    StackEntry: OpcodeData<T>,
253{
254    #[inline]
255    fn deserialize(&self) -> Result<T, TxScriptError> {
256        <StackEntry as OpcodeData<T>>::deserialize(&StackEntry::from_slice(self))
257    }
258
259    #[inline]
260    fn serialize(from: &T) -> Result<Self, SerializationError> {
261        <StackEntry as OpcodeData<T>>::serialize(from).map(|v| v.into_vec())
262    }
263}
264
265impl OpcodeData<Hash> for StackEntry {
266    #[inline]
267    fn deserialize(&self) -> Result<Hash, TxScriptError> {
268        Hash::try_from_slice(self).map_err(|_| TxScriptError::InvalidLengthOfBlockHash(self.len()))
269    }
270
271    #[inline]
272    fn serialize(from: &Hash) -> Result<Self, SerializationError> {
273        Ok(from.as_bytes().as_slice().into())
274    }
275}
276
277impl Stack {
278    pub(crate) fn new(inner: Vec<StackEntry>) -> Self {
279        Self { inner, pushed_bytes: 0 }
280    }
281
282    #[inline]
283    fn add_pushed_bytes(&mut self, bytes: usize) {
284        self.pushed_bytes = self.pushed_bytes.checked_add(bytes as u64).expect("stack pushed-bytes accounting should never overflow");
285    }
286
287    /// Returns the bytes pushed since the previous call and resets the counter.
288    #[inline]
289    pub fn pop_pushed_bytes(&mut self) -> u64 {
290        std::mem::take(&mut self.pushed_bytes)
291    }
292
293    #[inline]
294    pub fn insert(&mut self, index: usize, element: StackEntry) -> Result<(), TxScriptError> {
295        if element.len() > MAX_SCRIPT_ELEMENT_SIZE {
296            return Err(TxScriptError::ElementTooBig(element.len(), MAX_SCRIPT_ELEMENT_SIZE));
297        }
298        self.add_pushed_bytes(element.len());
299        self.inner.insert(index, element);
300        Ok(())
301    }
302
303    #[cfg(test)]
304    pub(crate) fn inner(&self) -> &[StackEntry] {
305        &self.inner
306    }
307
308    #[inline]
309    pub fn pop_items<const SIZE: usize, T: Debug>(&mut self) -> Result<[T; SIZE], TxScriptError>
310    where
311        StackEntry: OpcodeData<T>,
312    {
313        if self.len() < SIZE {
314            return Err(TxScriptError::InvalidStackOperation(SIZE, self.len()));
315        }
316        Ok(<[T; SIZE]>::try_from(
317            self.inner.split_off(self.len() - SIZE).iter().map(|v| v.deserialize()).collect::<Result<Vec<T>, _>>()?,
318        )
319        .expect("Already exact item"))
320    }
321
322    #[inline]
323    pub fn pop_raw<const SIZE: usize>(&mut self) -> Result<[StackEntry; SIZE], TxScriptError> {
324        if self.len() < SIZE {
325            return Err(TxScriptError::InvalidStackOperation(SIZE, self.len()));
326        }
327        Ok(<[StackEntry; SIZE]>::try_from(self.inner.split_off(self.len() - SIZE)).expect("Already exact item"))
328    }
329
330    #[inline]
331    pub fn peek_raw<const SIZE: usize>(&self) -> Result<[StackEntry; SIZE], TxScriptError> {
332        if self.len() < SIZE {
333            return Err(TxScriptError::InvalidStackOperation(SIZE, self.len()));
334        }
335        Ok(<[StackEntry; SIZE]>::try_from(self.inner[self.len() - SIZE..].to_vec()).expect("Already exact item"))
336    }
337
338    #[inline]
339    pub fn push_item<T: Debug>(&mut self, item: T) -> Result<(), TxScriptError>
340    where
341        StackEntry: OpcodeData<T>,
342    {
343        let v: StackEntry = OpcodeData::serialize(&item)?;
344        self.add_pushed_bytes(v.len());
345        Vec::push(&mut self.inner, v);
346        Ok(())
347    }
348
349    #[inline]
350    pub fn push_item_unmetered<T: Debug>(&mut self, item: T) -> Result<(), TxScriptError>
351    where
352        StackEntry: OpcodeData<T>,
353    {
354        let v: StackEntry = OpcodeData::serialize(&item)?;
355        Vec::push(&mut self.inner, v);
356        Ok(())
357    }
358
359    #[inline]
360    pub fn drop_items<const SIZE: usize>(&mut self) -> Result<(), TxScriptError> {
361        match self.len() >= SIZE {
362            true => {
363                self.inner.truncate(self.len() - SIZE);
364                Ok(())
365            }
366            false => Err(TxScriptError::InvalidStackOperation(SIZE, self.len())),
367        }
368    }
369
370    #[inline]
371    pub fn dup_items<const SIZE: usize>(&mut self) -> Result<(), TxScriptError> {
372        match self.len() >= SIZE {
373            true => {
374                let added_bytes = total_bytes(&self.inner[self.len() - SIZE..]);
375                self.add_pushed_bytes(added_bytes);
376                self.inner.extend_from_within(self.len() - SIZE..);
377                Ok(())
378            }
379            false => Err(TxScriptError::InvalidStackOperation(SIZE, self.len())),
380        }
381    }
382
383    #[inline]
384    pub fn over_items<const SIZE: usize>(&mut self) -> Result<(), TxScriptError> {
385        match self.len() >= 2 * SIZE {
386            true => {
387                let added_bytes = total_bytes(&self.inner[self.len() - 2 * SIZE..self.len() - SIZE]);
388                self.add_pushed_bytes(added_bytes);
389                self.inner.extend_from_within(self.len() - 2 * SIZE..self.len() - SIZE);
390                Ok(())
391            }
392            false => Err(TxScriptError::InvalidStackOperation(2 * SIZE, self.len())),
393        }
394    }
395
396    #[inline]
397    pub fn rot_items<const SIZE: usize>(&mut self) -> Result<(), TxScriptError> {
398        match self.len() >= 3 * SIZE {
399            true => {
400                // Rotate the trailing `3 * SIZE` frame left by `SIZE`, moving the oldest group to the top.
401                //
402                // SIZE = 1:
403                //   stack: [a, b, c, d, e, f]
404                //                   [d, e, f]
405                //                    << 1
406                //       -> [a, b, c, e, f, d]
407                //
408                // SIZE = 2:
409                //   stack: [a, b, c, d, e, f]
410                //          [a, b, c, d, e, f]
411                //           << 2
412                //       -> [c, d, e, f, a, b]
413                let len = self.len();
414                self.inner[len - 3 * SIZE..].rotate_left(SIZE);
415                Ok(())
416            }
417            false => Err(TxScriptError::InvalidStackOperation(3 * SIZE, self.len())),
418        }
419    }
420
421    #[inline]
422    pub fn swap_items<const SIZE: usize>(&mut self) -> Result<(), TxScriptError> {
423        match self.len() >= 2 * SIZE {
424            true => {
425                // Rotate the trailing `2 * SIZE` frame left by `SIZE`, swapping the top two groups.
426                //
427                // SIZE = 1:
428                //   stack: [a, b, c, d]
429                //                [c, d]
430                //                 << 1
431                //       -> [a, b, d, c]
432                //
433                // SIZE = 2:
434                //   stack: [a, b, c, d, e, f]
435                //                [c, d, e, f]
436                //                 << 2
437                //       -> [a, b, e, f, c, d]
438                let len = self.len();
439                self.inner[len - 2 * SIZE..].rotate_left(SIZE);
440                Ok(())
441            }
442            false => Err(TxScriptError::InvalidStackOperation(2 * SIZE, self.len())),
443        }
444    }
445
446    #[inline]
447    pub fn roll(&mut self, loc: usize) -> Result<(), TxScriptError> {
448        if loc >= self.len() {
449            return Err(TxScriptError::InvalidStackOperation(loc, self.len()));
450        }
451        if loc == 0 {
452            return Ok(());
453        }
454        let from = self.len() - loc - 1;
455        self.inner[from..].rotate_left(1);
456        Ok(())
457    }
458
459    pub fn clear(&mut self) {
460        self.inner.clear()
461    }
462
463    pub fn pop(&mut self) -> Result<StackEntry, TxScriptError> {
464        self.inner.pop().ok_or(TxScriptError::EmptyStack)
465    }
466
467    pub fn split_off(&mut self, at: usize) -> Vec<StackEntry> {
468        self.inner.split_off(at)
469    }
470
471    pub fn push(&mut self, item: StackEntry) -> Result<(), TxScriptError> {
472        if item.len() > MAX_SCRIPT_ELEMENT_SIZE {
473            return Err(TxScriptError::ElementTooBig(item.len(), MAX_SCRIPT_ELEMENT_SIZE));
474        }
475        self.add_pushed_bytes(item.len());
476        self.inner.push(item);
477        Ok(())
478    }
479
480    pub fn push_unmetered(&mut self, item: StackEntry) -> Result<(), TxScriptError> {
481        if item.len() > MAX_SCRIPT_ELEMENT_SIZE {
482            return Err(TxScriptError::ElementTooBig(item.len(), MAX_SCRIPT_ELEMENT_SIZE));
483        }
484        self.inner.push(item);
485        Ok(())
486    }
487
488    pub fn remove(&mut self, index: usize) -> StackEntry {
489        self.inner.remove(index)
490    }
491}
492
493#[cfg(test)]
494mod tests {
495    use super::OpcodeData;
496    use crate::data_stack::{SizedEncodeInt, serialize_i64};
497    use kaspa_txscript_errors::{SerializationError, TxScriptError};
498    use kaspa_utils::hex::FromHex;
499
500    // TestScriptNumBytes
501    #[test]
502    fn test_serialize() {
503        struct TestCase {
504            num: i64,
505            serialized: Vec<u8>,
506        }
507
508        let tests = vec![
509            TestCase { num: 0, serialized: vec![] },
510            TestCase { num: 1, serialized: Vec::from_hex("01").expect("failed parsing hex") },
511            TestCase { num: -1, serialized: Vec::from_hex("81").expect("failed parsing hex") },
512            TestCase { num: 127, serialized: Vec::from_hex("7f").expect("failed parsing hex") },
513            TestCase { num: -127, serialized: Vec::from_hex("ff").expect("failed parsing hex") },
514            TestCase { num: 128, serialized: Vec::from_hex("8000").expect("failed parsing hex") },
515            TestCase { num: -128, serialized: Vec::from_hex("8080").expect("failed parsing hex") },
516            TestCase { num: 129, serialized: Vec::from_hex("8100").expect("failed parsing hex") },
517            TestCase { num: -129, serialized: Vec::from_hex("8180").expect("failed parsing hex") },
518            TestCase { num: 256, serialized: Vec::from_hex("0001").expect("failed parsing hex") },
519            TestCase { num: -256, serialized: Vec::from_hex("0081").expect("failed parsing hex") },
520            TestCase { num: 32767, serialized: Vec::from_hex("ff7f").expect("failed parsing hex") },
521            TestCase { num: -32767, serialized: Vec::from_hex("ffff").expect("failed parsing hex") },
522            TestCase { num: 32768, serialized: Vec::from_hex("008000").expect("failed parsing hex") },
523            TestCase { num: -32768, serialized: Vec::from_hex("008080").expect("failed parsing hex") },
524            TestCase { num: 65535, serialized: Vec::from_hex("ffff00").expect("failed parsing hex") },
525            TestCase { num: -65535, serialized: Vec::from_hex("ffff80").expect("failed parsing hex") },
526            TestCase { num: 524288, serialized: Vec::from_hex("000008").expect("failed parsing hex") },
527            TestCase { num: -524288, serialized: Vec::from_hex("000088").expect("failed parsing hex") },
528            TestCase { num: 7340032, serialized: Vec::from_hex("000070").expect("failed parsing hex") },
529            TestCase { num: -7340032, serialized: Vec::from_hex("0000f0").expect("failed parsing hex") },
530            TestCase { num: 8388608, serialized: Vec::from_hex("00008000").expect("failed parsing hex") },
531            TestCase { num: -8388608, serialized: Vec::from_hex("00008080").expect("failed parsing hex") },
532            TestCase { num: 2147483647, serialized: Vec::from_hex("ffffff7f").expect("failed parsing hex") },
533            TestCase { num: -2147483647, serialized: Vec::from_hex("ffffffff").expect("failed parsing hex") },
534            // Values that are out of range for data that is interpreted as
535            // numbers before KIP-10 enabled, but are allowed as the result of numeric operations.
536            TestCase { num: 2147483648, serialized: Vec::from_hex("0000008000").expect("failed parsing hex") },
537            TestCase { num: -2147483648, serialized: Vec::from_hex("0000008080").expect("failed parsing hex") },
538            TestCase { num: 2415919104, serialized: Vec::from_hex("0000009000").expect("failed parsing hex") },
539            TestCase { num: -2415919104, serialized: Vec::from_hex("0000009080").expect("failed parsing hex") },
540            TestCase { num: 4294967295, serialized: Vec::from_hex("ffffffff00").expect("failed parsing hex") },
541            TestCase { num: -4294967295, serialized: Vec::from_hex("ffffffff80").expect("failed parsing hex") },
542            TestCase { num: 4294967296, serialized: Vec::from_hex("0000000001").expect("failed parsing hex") },
543            TestCase { num: -4294967296, serialized: Vec::from_hex("0000000081").expect("failed parsing hex") },
544            TestCase { num: 281474976710655, serialized: Vec::from_hex("ffffffffffff00").expect("failed parsing hex") },
545            TestCase { num: -281474976710655, serialized: Vec::from_hex("ffffffffffff80").expect("failed parsing hex") },
546            TestCase { num: 72057594037927935, serialized: Vec::from_hex("ffffffffffffff00").expect("failed parsing hex") },
547            TestCase { num: -72057594037927935, serialized: Vec::from_hex("ffffffffffffff80").expect("failed parsing hex") },
548            TestCase { num: 9223372036854775807, serialized: Vec::from_hex("ffffffffffffff7f").expect("failed parsing hex") },
549            TestCase { num: -9223372036854775807, serialized: Vec::from_hex("ffffffffffffffff").expect("failed parsing hex") },
550        ];
551
552        for test in tests {
553            let serialized: Vec<u8> = OpcodeData::<i64>::serialize(&test.num).unwrap();
554            assert_eq!(serialized, test.serialized);
555            assert_eq!(serialize_i64(test.num, Some(test.serialized.len())).unwrap().into_vec(), test.serialized);
556            if !test.serialized.is_empty() {
557                serialize_i64(test.num, Some(test.serialized.len() - 1)).unwrap_err();
558                // The default i64 serialization is minimal and cannot be encoded with less bytes.
559            }
560        }
561
562        // special case 9-byte i64
563        let r: Result<Vec<u8>, _> = OpcodeData::<i64>::serialize(&-9223372036854775808);
564        assert_eq!(r, Err(SerializationError::NumberTooLong(-9223372036854775808, 8)));
565    }
566
567    // TestMakeScriptNum
568    #[test]
569    fn test_deserialize() {
570        struct TestCase<T> {
571            serialized: Vec<u8>,
572            result: Result<T, TxScriptError>,
573        }
574
575        let tests = vec![
576            // Negative zero decodes as zero.
577            TestCase::<i64> { serialized: Vec::from_hex("80").expect("failed parsing hex"), result: Ok(0) },
578            // Minimally encoded valid values. Should not error and return expected integral number.
579            TestCase::<i64> { serialized: vec![], result: Ok(0) },
580            TestCase::<i64> { serialized: Vec::from_hex("01").expect("failed parsing hex"), result: Ok(1) },
581            TestCase::<i64> { serialized: Vec::from_hex("81").expect("failed parsing hex"), result: Ok(-1) },
582            TestCase::<i64> { serialized: Vec::from_hex("7f").expect("failed parsing hex"), result: Ok(127) },
583            TestCase::<i64> { serialized: Vec::from_hex("ff").expect("failed parsing hex"), result: Ok(-127) },
584            TestCase::<i64> { serialized: Vec::from_hex("8000").expect("failed parsing hex"), result: Ok(128) },
585            TestCase::<i64> { serialized: Vec::from_hex("8080").expect("failed parsing hex"), result: Ok(-128) },
586            TestCase::<i64> { serialized: Vec::from_hex("8100").expect("failed parsing hex"), result: Ok(129) },
587            TestCase::<i64> { serialized: Vec::from_hex("8180").expect("failed parsing hex"), result: Ok(-129) },
588            TestCase::<i64> { serialized: Vec::from_hex("0001").expect("failed parsing hex"), result: Ok(256) },
589            TestCase::<i64> { serialized: Vec::from_hex("0081").expect("failed parsing hex"), result: Ok(-256) },
590            TestCase::<i64> { serialized: Vec::from_hex("ff7f").expect("failed parsing hex"), result: Ok(32767) },
591            TestCase::<i64> { serialized: Vec::from_hex("ffff").expect("failed parsing hex"), result: Ok(-32767) },
592            TestCase::<i64> { serialized: Vec::from_hex("008000").expect("failed parsing hex"), result: Ok(32768) },
593            TestCase::<i64> { serialized: Vec::from_hex("008080").expect("failed parsing hex"), result: Ok(-32768) },
594            TestCase::<i64> { serialized: Vec::from_hex("ffff00").expect("failed parsing hex"), result: Ok(65535) },
595            TestCase::<i64> { serialized: Vec::from_hex("ffff80").expect("failed parsing hex"), result: Ok(-65535) },
596            TestCase::<i64> { serialized: Vec::from_hex("000008").expect("failed parsing hex"), result: Ok(524288) },
597            TestCase::<i64> { serialized: Vec::from_hex("000088").expect("failed parsing hex"), result: Ok(-524288) },
598            TestCase::<i64> { serialized: Vec::from_hex("000070").expect("failed parsing hex"), result: Ok(7340032) },
599            TestCase::<i64> { serialized: Vec::from_hex("0000f0").expect("failed parsing hex"), result: Ok(-7340032) },
600            TestCase::<i64> { serialized: Vec::from_hex("00008000").expect("failed parsing hex"), result: Ok(8388608) },
601            TestCase::<i64> { serialized: Vec::from_hex("00008080").expect("failed parsing hex"), result: Ok(-8388608) },
602            TestCase::<i64> { serialized: Vec::from_hex("ffffff7f").expect("failed parsing hex"), result: Ok(2147483647) },
603            TestCase::<i64> { serialized: Vec::from_hex("ffffffff").expect("failed parsing hex"), result: Ok(-2147483647) },
604            // Non-minimally encoded, but otherwise valid values. Decode to the number they encode.
605            TestCase::<i64> { serialized: Vec::from_hex("00").expect("failed parsing hex"), result: Ok(0) },
606            TestCase::<i64> { serialized: Vec::from_hex("0100").expect("failed parsing hex"), result: Ok(1) },
607            TestCase::<i64> { serialized: Vec::from_hex("7f00").expect("failed parsing hex"), result: Ok(127) },
608            TestCase::<i64> { serialized: Vec::from_hex("800000").expect("failed parsing hex"), result: Ok(128) },
609            TestCase::<i64> { serialized: Vec::from_hex("810000").expect("failed parsing hex"), result: Ok(129) },
610            TestCase::<i64> { serialized: Vec::from_hex("000100").expect("failed parsing hex"), result: Ok(256) },
611            TestCase::<i64> { serialized: Vec::from_hex("ff7f00").expect("failed parsing hex"), result: Ok(32767) },
612            TestCase::<i64> { serialized: Vec::from_hex("00800000").expect("failed parsing hex"), result: Ok(32768) },
613            TestCase::<i64> { serialized: Vec::from_hex("ffff0000").expect("failed parsing hex"), result: Ok(65535) },
614            TestCase::<i64> { serialized: Vec::from_hex("00000800").expect("failed parsing hex"), result: Ok(524288) },
615            TestCase::<i64> { serialized: Vec::from_hex("00007000").expect("failed parsing hex"), result: Ok(7340032) },
616            // Values above 8 bytes should always return error
617        ];
618        let kip10_tests = vec![
619            TestCase::<i64> { serialized: Vec::from_hex("0000008000").expect("failed parsing hex"), result: Ok(2147483648i64) },
620            TestCase::<i64> { serialized: Vec::from_hex("0000008080").expect("failed parsing hex"), result: Ok(-2147483648i64) },
621            TestCase::<i64> { serialized: Vec::from_hex("0000009000").expect("failed parsing hex"), result: Ok(2415919104i64) },
622            TestCase::<i64> { serialized: Vec::from_hex("0000009080").expect("failed parsing hex"), result: Ok(-2415919104i64) },
623            TestCase::<i64> { serialized: Vec::from_hex("ffffffff00").expect("failed parsing hex"), result: Ok(4294967295i64) },
624            TestCase::<i64> { serialized: Vec::from_hex("ffffffff80").expect("failed parsing hex"), result: Ok(-4294967295i64) },
625            TestCase::<i64> { serialized: Vec::from_hex("0000000001").expect("failed parsing hex"), result: Ok(4294967296i64) },
626            TestCase::<i64> { serialized: Vec::from_hex("0000000081").expect("failed parsing hex"), result: Ok(-4294967296i64) },
627            TestCase::<i64> {
628                serialized: Vec::from_hex("ffffffffffff00").expect("failed parsing hex"),
629                result: Ok(281474976710655i64),
630            },
631            TestCase::<i64> {
632                serialized: Vec::from_hex("ffffffffffff80").expect("failed parsing hex"),
633                result: Ok(-281474976710655i64),
634            },
635            TestCase::<i64> {
636                serialized: Vec::from_hex("ffffffffffffff00").expect("failed parsing hex"),
637                result: Ok(72057594037927935i64),
638            },
639            TestCase::<i64> {
640                serialized: Vec::from_hex("ffffffffffffff80").expect("failed parsing hex"),
641                result: Ok(-72057594037927935i64),
642            },
643            TestCase::<i64> {
644                serialized: Vec::from_hex("ffffffffffffff7f").expect("failed parsing hex"),
645                result: Ok(9223372036854775807i64),
646            },
647            TestCase::<i64> {
648                serialized: Vec::from_hex("ffffffffffffffff").expect("failed parsing hex"),
649                result: Ok(-9223372036854775807i64),
650            },
651            // Values that are out of range for data that is interpreted as script numbers.
652            // Should error and return 0.
653            TestCase::<i64> {
654                serialized: Vec::from_hex("000000000000008080").expect("failed parsing hex"),
655                result: Err(TxScriptError::NumberTooBig(
656                    "numeric value encoded as [0, 0, 0, 0, 0, 0, 0, 80, 80] is 9 bytes which exceeds the max allowed of 8".to_string(),
657                )),
658            },
659        ];
660        let test_of_size_5 = vec![
661            TestCase::<SizedEncodeInt<5>> {
662                serialized: Vec::from_hex("ffffffff7f").expect("failed parsing hex"),
663                result: Ok(SizedEncodeInt::<5>(549755813887)),
664            },
665            TestCase::<SizedEncodeInt<5>> {
666                serialized: Vec::from_hex("ffffffffff").expect("failed parsing hex"),
667                result: Ok(SizedEncodeInt::<5>(-549755813887)),
668            },
669            TestCase::<SizedEncodeInt<5>> {
670                serialized: Vec::from_hex("0009000100").expect("failed parsing hex"),
671                result: Ok(SizedEncodeInt::<5>(16779520)),
672            },
673        ];
674
675        let test_of_size_8 = vec![
676            TestCase::<SizedEncodeInt<8>> {
677                serialized: Vec::from_hex("ffffffffffffff7f").expect("failed parsing hex"),
678                result: Ok(SizedEncodeInt::<8>(i64::MAX)),
679            },
680            TestCase::<SizedEncodeInt<8>> {
681                serialized: Vec::from_hex("ffffffffffffffff").expect("failed parsing hex"),
682                result: Ok(SizedEncodeInt::<8>(i64::MIN + 1)),
683            },
684        ];
685
686        let test_of_size_9 = vec![
687            TestCase::<SizedEncodeInt<9>> {
688                serialized: Vec::from_hex("ffffffffffffffffff").expect("failed parsing hex"),
689                result: Err(TxScriptError::NotMinimalData(
690                    "numeric value encoded as [ff, ff, ff, ff, ff, ff, ff, ff, ff] is longer than 8 bytes".to_string(),
691                )),
692            },
693            TestCase::<SizedEncodeInt<9>> {
694                serialized: Vec::from_hex("ffffffffffffffff").expect("failed parsing hex"),
695                result: Ok(SizedEncodeInt::<9>(i64::MIN + 1)),
696            },
697        ];
698
699        let test_of_size_10 = vec![TestCase::<SizedEncodeInt<10>> {
700            serialized: Vec::from_hex("00000000000000000000").expect("failed parsing hex"),
701            result: Err(TxScriptError::NotMinimalData(
702                "numeric value encoded as [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] is longer than 8 bytes".to_string(),
703            )),
704        }];
705
706        let test_bool = vec![
707            TestCase::<bool> { serialized: Vec::from_hex("").expect("failed parsing hex"), result: Ok(false) },
708            TestCase::<bool> { serialized: Vec::from_hex("00").expect("failed parsing hex"), result: Ok(false) },
709            TestCase::<bool> { serialized: Vec::from_hex("0000").expect("failed parsing hex"), result: Ok(false) },
710            TestCase::<bool> { serialized: Vec::from_hex("0011").expect("failed parsing hex"), result: Ok(true) },
711            TestCase::<bool> { serialized: Vec::from_hex("80").expect("failed parsing hex"), result: Ok(false) }, // Negative zero
712            TestCase::<bool> { serialized: Vec::from_hex("8011").expect("failed parsing hex"), result: Ok(true) }, // MSB by itself is negative zero, but the whole number isn't
713            TestCase::<bool> { serialized: Vec::from_hex("8080").expect("failed parsing hex"), result: Ok(true) }, // All bytes are negative zeroes by themselves, but the whole number isn't
714            TestCase::<bool> { serialized: Vec::from_hex("1234").expect("failed parsing hex"), result: Ok(true) },
715            TestCase::<bool> { serialized: Vec::from_hex("ffffffff").expect("failed parsing hex"), result: Ok(true) },
716        ];
717
718        for test in tests {
719            // Ensure the error code is of the expected type and the error
720            // code matches the value specified in the test instance.
721            assert_eq!(test.serialized.deserialize(), test.result);
722        }
723
724        for test in test_of_size_5 {
725            // Ensure the error code is of the expected type and the error
726            // code matches the value specified in the test instance.
727            assert_eq!(test.serialized.deserialize(), test.result);
728        }
729
730        for test in test_of_size_8 {
731            // Ensure the error code is of the expected type and the error
732            // code matches the value specified in the test instance.
733            assert_eq!(test.serialized.deserialize(), test.result);
734        }
735
736        for test in test_of_size_9 {
737            // Ensure the error code is of the expected type and the error
738            // code matches the value specified in the test instance.
739            assert_eq!(test.serialized.deserialize(), test.result);
740        }
741
742        for test in test_of_size_10 {
743            // Ensure the error code is of the expected type and the error
744            // code matches the value specified in the test instance.
745            assert_eq!(test.serialized.deserialize(), test.result);
746        }
747
748        for test in test_bool {
749            // Ensure the error code is of the expected type and the error
750            // code matches the value specified in the test instance.
751            assert_eq!(test.serialized.deserialize(), test.result);
752        }
753        for test in kip10_tests {
754            // Ensure the error code is of the expected type and the error
755            // code matches the value specified in the test instance.
756            assert_eq!(test.serialized.deserialize(), test.result);
757        }
758    }
759}