Skip to main content

blvm_consensus/script/
stack.rs

1//! Stack types and operations for script execution.
2//!
3//! StackElement, to_stack_element, and cast_to_bool are used by both
4//! production and non-production script execution paths.
5
6use crate::types::*;
7
8#[cfg(feature = "production")]
9use smallvec::SmallVec;
10
11/// Stack element: inline up to 80 bytes when production (sigs, pubkeys, hashes), else Vec<u8>.
12#[cfg(feature = "production")]
13pub type StackElement = SmallVec<[u8; 80]>;
14#[cfg(not(feature = "production"))]
15pub type StackElement = ByteString;
16
17/// Convert bytes to StackElement (for tests and callers needing explicit conversion).
18#[inline]
19pub fn to_stack_element(data: &[u8]) -> StackElement {
20    #[cfg(feature = "production")]
21    return SmallVec::from_slice(data);
22    #[cfg(not(feature = "production"))]
23    return data.to_vec();
24}
25
26/// CastToBool: truthiness check for stack elements (BIP62/consensus).
27/// Returns true if ANY byte is non-zero, except for "negative zero" (0x80 in last byte, rest zeros).
28#[cfg(feature = "production")]
29#[inline(always)]
30pub fn cast_to_bool(v: &[u8]) -> bool {
31    for i in 0..v.len() {
32        if v[i] != 0 {
33            // Negative zero: all zeros except 0x80 in the last byte
34            if i == v.len() - 1 && v[i] == 0x80 {
35                return false;
36            }
37            return true;
38        }
39    }
40    false
41}
42
43#[cfg(not(feature = "production"))]
44#[inline]
45pub fn cast_to_bool(v: &[u8]) -> bool {
46    for i in 0..v.len() {
47        if v[i] != 0 {
48            // Negative zero: all zeros except 0x80 in the last byte
49            if i == v.len() - 1 && v[i] == 0x80 {
50                return false;
51            }
52            return true;
53        }
54    }
55    false
56}