blvm_consensus/
locktime.rs1use crate::constants::LOCKTIME_THRESHOLD;
7use crate::types::*;
8use blvm_spec_lock::spec_locked;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum LocktimeType {
13 BlockHeight,
15 Timestamp,
17}
18
19#[spec_locked("5.4.7")]
23#[inline]
24pub fn get_locktime_type(locktime: u32) -> LocktimeType {
25 if locktime < LOCKTIME_THRESHOLD {
26 LocktimeType::BlockHeight
27 } else {
28 LocktimeType::Timestamp
29 }
30}
31
32#[inline]
35#[spec_locked("5.4.7")]
36pub fn check_bip65(tx_locktime: u32, stack_locktime: u32) -> bool {
37 tx_locktime != 0
38 && locktime_types_match(tx_locktime, stack_locktime)
39 && tx_locktime >= stack_locktime
40}
41
42#[inline]
46#[spec_locked("5.4.7")]
47pub fn locktime_types_match(locktime1: u32, locktime2: u32) -> bool {
48 get_locktime_type(locktime1) == get_locktime_type(locktime2)
49}
50
51#[spec_locked("5.4.7")]
62pub fn decode_locktime_value(bytes: &[u8]) -> Option<u32> {
63 if bytes.len() > 5 {
64 return None; }
66
67 debug_assert!(
69 bytes.len() <= 5,
70 "Locktime byte string length ({}) must be <= 5",
71 bytes.len()
72 );
73
74 let mut value: u32 = 0;
75 for (i, &byte) in bytes.iter().enumerate() {
76 if i >= 4 {
77 break; }
79
80 debug_assert!(i < 4, "Byte index ({i}) must be < 4 for locktime decoding");
82
83 let shift_amount = i * 8;
85 debug_assert!(
86 shift_amount < 32,
87 "Shift amount ({shift_amount}) must be < 32 (i: {i})"
88 );
89
90 value |= (byte as u32) << shift_amount;
91 }
92
93 Some(value)
96}
97
98#[spec_locked("5.4.7")]
103pub fn encode_locktime_value(value: u32) -> ByteString {
104 let mut bytes = Vec::new();
105
106 let mut temp = value;
108 while temp > 0 {
109 bytes.push((temp & 0xff) as u8);
110 temp >>= 8;
111
112 debug_assert!(
115 temp < value || bytes.len() <= 4,
116 "Locktime encoding loop must terminate (temp: {}, value: {}, bytes: {})",
117 temp,
118 value,
119 bytes.len()
120 );
121 }
122
123 if bytes.is_empty() {
125 bytes.push(0);
126 }
127
128 let len = bytes.len();
130 debug_assert!(
131 !bytes.is_empty() && len <= 4,
132 "Encoded locktime length ({len}) must be between 1 and 4 bytes"
133 );
134
135 bytes
136}
137
138#[inline]
144#[spec_locked("5.5")]
145pub fn extract_sequence_type_flag(sequence: u32) -> bool {
146 (sequence & 0x00400000) != 0
147}
148
149#[inline]
153#[spec_locked("5.5")]
154pub fn extract_sequence_locktime_value(sequence: u32) -> u16 {
155 (sequence & 0x0000ffff) as u16
156}
157
158#[inline]
162#[spec_locked("5.5")]
163pub fn is_sequence_disabled(sequence: u32) -> bool {
164 (sequence & 0x80000000) != 0
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_get_locktime_type_block_height() {
173 assert_eq!(get_locktime_type(100), LocktimeType::BlockHeight);
174 assert_eq!(
175 get_locktime_type(LOCKTIME_THRESHOLD - 1),
176 LocktimeType::BlockHeight
177 );
178 }
179
180 #[test]
181 fn test_get_locktime_type_timestamp() {
182 assert_eq!(
183 get_locktime_type(LOCKTIME_THRESHOLD),
184 LocktimeType::Timestamp
185 );
186 assert_eq!(get_locktime_type(1_000_000_000), LocktimeType::Timestamp);
187 }
188
189 #[test]
190 fn test_locktime_types_match() {
191 assert!(locktime_types_match(100, 200));
192 assert!(locktime_types_match(
193 LOCKTIME_THRESHOLD,
194 LOCKTIME_THRESHOLD + 1000
195 ));
196 assert!(!locktime_types_match(100, LOCKTIME_THRESHOLD));
197 }
198
199 #[test]
200 fn test_decode_locktime_value() {
201 assert_eq!(decode_locktime_value(&vec![100, 0, 0, 0]), Some(100));
202 assert_eq!(decode_locktime_value(&vec![0]), Some(0));
203 assert_eq!(
204 decode_locktime_value(&vec![0xff, 0xff, 0xff, 0xff]),
205 Some(0xffffffff)
206 );
207 assert_eq!(decode_locktime_value(&vec![0; 6]), None); }
209
210 #[test]
211 fn test_encode_locktime_value() {
212 assert_eq!(encode_locktime_value(100), vec![100]); assert_eq!(encode_locktime_value(0), vec![0]);
215 assert_eq!(
216 encode_locktime_value(0x12345678),
217 vec![0x78, 0x56, 0x34, 0x12]
218 );
219 assert_eq!(encode_locktime_value(0x00001234), vec![0x34, 0x12]);
221 assert_eq!(
222 encode_locktime_value(0x12345600),
223 vec![0x00, 0x56, 0x34, 0x12]
224 );
225 }
226
227 #[test]
228 fn test_extract_sequence_type_flag() {
229 assert!(extract_sequence_type_flag(0x00400000));
230 assert!(!extract_sequence_type_flag(0x00000000));
231 assert!(extract_sequence_type_flag(0x00410000));
232 }
233
234 #[test]
235 fn test_extract_sequence_locktime_value() {
236 assert_eq!(extract_sequence_locktime_value(0x00001234), 0x1234);
237 assert_eq!(extract_sequence_locktime_value(0x00401234), 0x1234); }
239
240 #[test]
241 fn test_is_sequence_disabled() {
242 assert!(is_sequence_disabled(0x80000000));
243 assert!(!is_sequence_disabled(0x00000000));
244 assert!(is_sequence_disabled(0x80010000));
245 }
246}