sv/script/
stack.rs

1use crate::util::{Error, Result};
2use num_bigint::{BigInt, Sign};
3use num_traits::Zero;
4
5/// Pops a bool off the stack
6#[inline]
7pub fn pop_bool(stack: &mut Vec<Vec<u8>>) -> Result<bool> {
8    if stack.len() == 0 {
9        let msg = "Cannot pop bool, empty stack".to_string();
10        return Err(Error::ScriptError(msg));
11    }
12    let top = stack.pop().unwrap();
13    // Bools cannot be popped having more than 32-bits, but may be used in other ways
14    if top.len() > 4 {
15        let msg = format!("Cannot pop bool, len too long {}", top.len());
16        return Err(Error::ScriptError(msg));
17    }
18    Ok(decode_bool(&top))
19}
20
21/// Pops a pre-genesis number off the stack
22#[inline]
23pub fn pop_num(stack: &mut Vec<Vec<u8>>) -> Result<i32> {
24    if stack.len() == 0 {
25        let msg = "Cannot pop num, empty stack".to_string();
26        return Err(Error::ScriptError(msg));
27    }
28    let top = stack.pop().unwrap();
29    // Numbers cannot be popped having more than 4 bytes, but may overflow on the stack to 5 bytes
30    // after certain operations and may be used as byte vectors.
31    if top.len() > 4 {
32        let msg = format!("Cannot pop num, len too long {}", top.len());
33        return Err(Error::ScriptError(msg));
34    }
35    Ok(decode_num(&top)? as i32)
36}
37
38/// Pops a bigint number off the stack
39#[inline]
40pub fn pop_bigint(stack: &mut Vec<Vec<u8>>) -> Result<BigInt> {
41    if stack.len() == 0 {
42        let msg = "Cannot pop bigint, empty stack".to_string();
43        return Err(Error::ScriptError(msg));
44    }
45    let mut top = stack.pop().unwrap();
46    Ok(decode_bigint(&mut top))
47}
48
49/// Converts a stack item to a bool
50#[inline]
51pub fn decode_bool(s: &[u8]) -> bool {
52    if s.len() == 0 {
53        return false;
54    }
55    for i in 0..s.len() - 1 {
56        if s[i] != 0 {
57            return true;
58        }
59    }
60    s[s.len() - 1] & 127 != 0
61}
62
63/// Converts a stack item to a number
64#[inline]
65pub fn decode_num(s: &[u8]) -> Result<i64> {
66    let mut val = match s.len() {
67        0 => return Ok(0),
68        1 => (s[0] & 127) as i64,
69        2 => (((s[1] & 127) as i64) << 8) + ((s[0] as i64) << 0),
70        3 => (((s[2] & 127) as i64) << 16) + ((s[1] as i64) << 8) + ((s[0] as i64) << 0),
71        4 => {
72            (((s[3] & 127) as i64) << 24)
73                + ((s[2] as i64) << 16)
74                + ((s[1] as i64) << 8)
75                + ((s[0] as i64) << 0)
76        }
77        _ => {
78            for i in 4..s.len() - 1 {
79                if s[i] != 0 {
80                    return Err(Error::ScriptError("Number too big".to_string()));
81                }
82            }
83            if s[s.len() - 1] & 127 != 0 {
84                return Err(Error::ScriptError("Number too big".to_string()));
85            }
86            ((s[3] as i64) << 24)
87                + ((s[2] as i64) << 16)
88                + ((s[1] as i64) << 8)
89                + ((s[0] as i64) << 0)
90        }
91    };
92    if s[s.len() - 1] & 128 != 0 {
93        val = 0 - val;
94    }
95    Ok(val)
96}
97
98/// Converts a number to a 32-bit stack item
99#[inline]
100pub fn encode_num(val: i64) -> Result<Vec<u8>> {
101    // Range: [-2^31+1, 2^31-1]
102    if val > 2147483647 || val < -2147483647 {
103        return Err(Error::ScriptError("Number out of range".to_string()));
104    }
105    let (posval, negmask) = if val < 0 { (-val, 128) } else { (val, 0) };
106    if posval == 0 {
107        Ok(vec![])
108    } else if posval < 128 {
109        Ok(vec![(posval as u8) | negmask])
110    } else if posval < 32768 {
111        Ok(vec![(posval >> 0) as u8, ((posval >> 8) as u8) | negmask])
112    } else if posval < 8388608 {
113        Ok(vec![
114            (posval >> 0) as u8,
115            (posval >> 8) as u8,
116            ((posval >> 16) as u8) | negmask,
117        ])
118    } else {
119        Ok(vec![
120            (posval >> 0) as u8,
121            (posval >> 8) as u8,
122            (posval >> 16) as u8,
123            ((posval >> 24) as u8) | negmask,
124        ])
125    }
126}
127
128/// Converts a stack item to a big int number
129#[inline]
130pub fn decode_bigint(s: &mut [u8]) -> BigInt {
131    let len = s.len();
132    if s.len() == 0 {
133        return BigInt::zero();
134    }
135    let mut sign = Sign::Plus;
136    if s[len - 1] & 0x80 == 0x80 {
137        sign = Sign::Minus;
138    }
139    s[len - 1] &= !0x80;
140    BigInt::from_bytes_le(sign, &s)
141}
142
143/// Converts a big int number to a stack item
144#[inline]
145pub fn encode_bigint(val: BigInt) -> Vec<u8> {
146    let mut result = val.to_bytes_le();
147    if result.1[result.1.len() - 1] & 0x80 == 0x80 {
148        result.1.push(match result.0 {
149            Sign::Plus | Sign::NoSign => 0x00,
150            Sign::Minus => 0x80,
151        });
152    } else if result.0 == Sign::Minus {
153        let len = result.1.len();
154        result.1[len - 1] |= 0x80;
155    }
156    if result.1.len() == 1 && result.1[0] == 0 {
157        return vec![];
158    }
159    result.1
160}
161
162#[cfg(test)]
163mod tests {
164    use super::*;
165
166    #[test]
167    fn decode_bool_tests() {
168        assert!(decode_bool(&[1]) == true);
169        assert!(decode_bool(&[255, 0, 0, 0]) == true);
170        assert!(decode_bool(&[0, 0, 0, 129]) == true);
171        assert!(decode_bool(&[0]) == false);
172        assert!(decode_bool(&[0, 0, 0, 0]) == false);
173        assert!(decode_bool(&[0, 0, 0, 128]) == false);
174        assert!(decode_bool(&[]) == false);
175    }
176
177    #[test]
178    fn pop_bool_tests() {
179        assert!(pop_bool(&mut vec![vec![1]]).unwrap() == true);
180        assert!(pop_bool(&mut vec![vec![0, 0, 0, 127]]).unwrap() == true);
181        assert!(pop_bool(&mut vec![vec![0, 0, 0, 127]]).unwrap() == true);
182        assert!(pop_bool(&mut vec![]).is_err());
183        assert!(pop_bool(&mut vec![vec![0, 0, 0, 0, 0]]).is_err());
184        assert!(pop_bool(&mut vec![vec![]]).unwrap() == false);
185        assert!(pop_bool(&mut vec![vec![0]]).unwrap() == false);
186        assert!(pop_bool(&mut vec![vec![0, 0, 0, 0]]).unwrap() == false);
187        assert!(pop_bool(&mut vec![vec![0, 0, 0, 128]]).unwrap() == false);
188    }
189
190    #[test]
191    fn encode_decode_num_tests() {
192        // Range checks
193        assert!(encode_num(2147483647).is_ok());
194        assert!(encode_num(-2147483647).is_ok());
195        assert!(encode_num(2147483648).is_err());
196        assert!(encode_num(-2147483648).is_err());
197        // Encode decode
198        assert!(decode_num(&encode_num(0).unwrap()).unwrap() == 0);
199        assert!(decode_num(&encode_num(1).unwrap()).unwrap() == 1);
200        assert!(decode_num(&encode_num(-1).unwrap()).unwrap() == -1);
201        assert!(decode_num(&encode_num(1111).unwrap()).unwrap() == 1111);
202        assert!(decode_num(&encode_num(-1111).unwrap()).unwrap() == -1111);
203        assert!(decode_num(&encode_num(111111).unwrap()).unwrap() == 111111);
204        assert!(decode_num(&encode_num(-111111).unwrap()).unwrap() == -111111);
205        assert!(decode_num(&encode_num(2147483647).unwrap()).unwrap() == 2147483647);
206        assert!(decode_num(&encode_num(-2147483647).unwrap()).unwrap() == -2147483647);
207    }
208
209    #[test]
210    fn pop_num_tests() {
211        assert!(pop_num(&mut vec![vec![]]).unwrap() == 0);
212        assert!(pop_num(&mut vec![vec![1]]).unwrap() == 1);
213        assert!(pop_num(&mut vec![vec![129]]).unwrap() == -1);
214        assert!(pop_num(&mut vec![vec![0, 0, 0, 0]]).unwrap() == 0);
215        assert!(pop_num(&mut vec![vec![0, 0, 0, 0, 0]]).is_err());
216    }
217}