bitcoin_script_analyzer/util/
locktime.rs1use time::{format_description, OffsetDateTime};
2
3pub const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
4pub const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000ffff;
5
6#[derive(PartialEq, Eq)]
7pub enum LocktimeType {
8 Height,
9 Time,
10}
11
12impl LocktimeType {
13 pub fn new(value: u32, relative: bool) -> Self {
14 if value
15 < if relative {
16 SEQUENCE_LOCKTIME_TYPE_FLAG
17 } else {
18 500000000
19 }
20 {
21 Self::Height
22 } else {
23 Self::Time
24 }
25 }
26}
27
28pub fn locktime_type_equals(a: u32, b: u32, relative: bool) -> bool {
29 LocktimeType::new(a, relative) == LocktimeType::new(b, relative)
30}
31
32pub fn absolute_timelock_height_to_string(n: u32) -> String {
36 format!("at block {n}")
37}
38
39pub fn absolute_timelock_time_to_string(n: u32) -> String {
40 const DATE_FORMAT_STR: &str =
41 "on [year]-[month]-[day] [hour]:[minute]:[second] ([unix_timestamp] seconds since unix epoch)";
42
43 let date = OffsetDateTime::from_unix_timestamp(n as i64).unwrap();
44 let format = format_description::parse_borrowed::<2>(DATE_FORMAT_STR).unwrap();
45
46 date.format(&format).unwrap()
47}
48
49pub fn relative_timelock_height_to_string(n: u32) -> String {
50 format!("in {n} blocks")
51}
52
53pub fn relative_timelock_time_to_string(n: u32) -> String {
54 let mut t = (n & SEQUENCE_LOCKTIME_MASK) * 512;
55 let mut output = format!("in {}s", t % 60);
56 let mut prev = 60;
57 for unit in [('m', 60), ('h', 24), ('d', 999)] {
58 t /= prev;
59 if t == 0 {
60 break;
61 }
62 output.insert_str(3, &format!("{}{} ", t % unit.1, unit.0));
63 prev = unit.1;
64 }
65 output
66}
67
68pub fn locktime_to_string_unchecked(n: u32, relative: bool, type_: LocktimeType) -> String {
69 (match (relative, type_) {
70 (false, LocktimeType::Height) => absolute_timelock_height_to_string,
71 (false, LocktimeType::Time) => absolute_timelock_time_to_string,
72 (true, LocktimeType::Height) => relative_timelock_height_to_string,
73 (true, LocktimeType::Time) => relative_timelock_time_to_string,
74 })(n)
75}
76
77pub fn locktime_to_string(n: u32, relative: bool) -> String {
78 locktime_to_string_unchecked(n, relative, LocktimeType::new(n, relative))
79}