Skip to main content

xrpl_common_stdlib/host/
chain.rs

1use crate::host::{
2    Error, Result, amendment_enabled as host_amendment_enabled, base_fee as host_base_fee,
3    error_codes::match_result_code_with_expected_bytes, ldgr_index, parent_ldgr_hash,
4    parent_ldgr_time,
5};
6
7pub fn ledger_sqn() -> Result<u32> {
8    let mut uint_bytes = [0u8; 4];
9    let rescode = unsafe { ldgr_index(uint_bytes.as_mut_ptr(), 4) };
10    match_result_code_with_expected_bytes(rescode, 4, || u32::from_le_bytes(uint_bytes))
11}
12
13pub fn parent_ledger_time() -> Result<u32> {
14    let mut uint_bytes = [0u8; 4];
15    let rescode = unsafe { parent_ldgr_time(uint_bytes.as_mut_ptr(), 4) };
16    match_result_code_with_expected_bytes(rescode, 4, || u32::from_le_bytes(uint_bytes))
17}
18
19pub fn parent_ledger_hash() -> Result<[u8; 32]> {
20    let mut bytes = [0u8; 32];
21    let rescode = unsafe { parent_ldgr_hash(bytes.as_mut_ptr(), 32) };
22    match_result_code_with_expected_bytes(rescode, 32, || bytes)
23}
24
25pub fn base_fee() -> Result<u32> {
26    let mut uint_bytes = [0u8; 4];
27    let rescode = unsafe { host_base_fee(uint_bytes.as_mut_ptr(), 4) };
28    match_result_code_with_expected_bytes(rescode, 4, || u32::from_le_bytes(uint_bytes))
29}
30
31pub fn amendment_enabled(hash: &[u8; 32]) -> Result<bool> {
32    let rescode = unsafe { host_amendment_enabled(hash.as_ptr(), 32) };
33    match rescode {
34        0 => Result::Ok(false),
35        1 => Result::Ok(true),
36        _ => Result::Err(Error::from_code(rescode)),
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use crate::host::error_codes::SOME_ERROR;
44    use crate::host::host_bindings_trait::MockHostBindings;
45    use crate::host::setup_mock;
46
47    fn write_u32(ptr: *mut u8, value: u32) {
48        let bytes = value.to_le_bytes();
49        unsafe {
50            for (i, b) in bytes.iter().enumerate() {
51                *ptr.add(i) = *b;
52            }
53        }
54    }
55
56    fn write_hash(ptr: *mut u8, fill: u8) {
57        unsafe {
58            for i in 0..32 {
59                *ptr.add(i) = fill;
60            }
61        }
62    }
63
64    // ---- ledger_sqn ----
65
66    #[test]
67    fn test_ledger_sqn_success() {
68        let mut mock = MockHostBindings::new();
69        mock.expect_ldgr_index().times(1).returning(|ptr, _| {
70            write_u32(ptr, 42);
71            4
72        });
73        let _guard = setup_mock(mock);
74
75        let result = ledger_sqn();
76        assert!(result.is_ok());
77        assert_eq!(result.unwrap(), 42);
78    }
79
80    #[test]
81    fn test_ledger_sqn_error() {
82        let mut mock = MockHostBindings::new();
83        mock.expect_ldgr_index()
84            .times(1)
85            .returning(|_, _| SOME_ERROR);
86        let _guard = setup_mock(mock);
87
88        assert!(ledger_sqn().is_err());
89    }
90
91    // ---- parent_ledger_time ----
92
93    #[test]
94    fn test_parent_ledger_time_success() {
95        let mut mock = MockHostBindings::new();
96        mock.expect_parent_ldgr_time().times(1).returning(|ptr, _| {
97            write_u32(ptr, 1_000_000);
98            4
99        });
100        let _guard = setup_mock(mock);
101
102        let result = parent_ledger_time();
103        assert!(result.is_ok());
104        assert_eq!(result.unwrap(), 1_000_000);
105    }
106
107    #[test]
108    fn test_parent_ledger_time_error() {
109        let mut mock = MockHostBindings::new();
110        mock.expect_parent_ldgr_time()
111            .times(1)
112            .returning(|_, _| SOME_ERROR);
113        let _guard = setup_mock(mock);
114
115        assert!(parent_ledger_time().is_err());
116    }
117
118    // ---- parent_ledger_hash ----
119
120    #[test]
121    fn test_parent_ledger_hash_success() {
122        let mut mock = MockHostBindings::new();
123        mock.expect_parent_ldgr_hash().times(1).returning(|ptr, _| {
124            write_hash(ptr, 0xAB);
125            32
126        });
127        let _guard = setup_mock(mock);
128
129        let result = parent_ledger_hash();
130        assert!(result.is_ok());
131        assert_eq!(result.unwrap(), [0xAB; 32]);
132    }
133
134    #[test]
135    fn test_parent_ledger_hash_error() {
136        let mut mock = MockHostBindings::new();
137        mock.expect_parent_ldgr_hash()
138            .times(1)
139            .returning(|_, _| SOME_ERROR);
140        let _guard = setup_mock(mock);
141
142        assert!(parent_ledger_hash().is_err());
143    }
144
145    // ---- base_fee ----
146
147    #[test]
148    fn test_base_fee_success() {
149        let mut mock = MockHostBindings::new();
150        mock.expect_base_fee().times(1).returning(|ptr, _| {
151            write_u32(ptr, 12);
152            4
153        });
154        let _guard = setup_mock(mock);
155
156        let result = base_fee();
157        assert!(result.is_ok());
158        assert_eq!(result.unwrap(), 12);
159    }
160
161    #[test]
162    fn test_base_fee_error() {
163        let mut mock = MockHostBindings::new();
164        mock.expect_base_fee().times(1).returning(|_, _| SOME_ERROR);
165        let _guard = setup_mock(mock);
166
167        assert!(base_fee().is_err());
168    }
169
170    // ---- amendment_enabled ----
171
172    #[test]
173    fn test_amendment_enabled_true() {
174        let mut mock = MockHostBindings::new();
175        mock.expect_amendment_enabled().times(1).returning(|_, _| 1);
176        let _guard = setup_mock(mock);
177
178        assert!(amendment_enabled(&[0u8; 32]).unwrap());
179    }
180
181    #[test]
182    fn test_amendment_enabled_false() {
183        let mut mock = MockHostBindings::new();
184        mock.expect_amendment_enabled().times(1).returning(|_, _| 0);
185        let _guard = setup_mock(mock);
186
187        assert!(!amendment_enabled(&[0u8; 32]).unwrap());
188    }
189
190    #[test]
191    fn test_amendment_enabled_error() {
192        let mut mock = MockHostBindings::new();
193        mock.expect_amendment_enabled()
194            .times(1)
195            .returning(|_, _| SOME_ERROR);
196        let _guard = setup_mock(mock);
197
198        assert!(amendment_enabled(&[0u8; 32]).is_err());
199    }
200}