Skip to main content

xrpl_wasm_stdlib/core/
chain.rs

1use crate::host::{
2    Error, Result, amendment_enabled as host_amendment_enabled,
3    error_codes::match_result_code_with_expected_bytes, get_base_fee, get_ledger_sqn,
4    get_parent_ledger_hash, get_parent_ledger_time,
5};
6
7pub fn ledger_sqn() -> Result<u32> {
8    let mut uint_bytes = [0u8; 4];
9    let rescode = unsafe { get_ledger_sqn(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 { get_parent_ledger_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 { get_parent_ledger_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 { get_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::INTERNAL_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_get_ledger_sqn().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_get_ledger_sqn()
84            .times(1)
85            .returning(|_, _| INTERNAL_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_get_parent_ledger_time()
97            .times(1)
98            .returning(|ptr, _| {
99                write_u32(ptr, 1_000_000);
100                4
101            });
102        let _guard = setup_mock(mock);
103
104        let result = parent_ledger_time();
105        assert!(result.is_ok());
106        assert_eq!(result.unwrap(), 1_000_000);
107    }
108
109    #[test]
110    fn test_parent_ledger_time_error() {
111        let mut mock = MockHostBindings::new();
112        mock.expect_get_parent_ledger_time()
113            .times(1)
114            .returning(|_, _| INTERNAL_ERROR);
115        let _guard = setup_mock(mock);
116
117        assert!(parent_ledger_time().is_err());
118    }
119
120    // ---- parent_ledger_hash ----
121
122    #[test]
123    fn test_parent_ledger_hash_success() {
124        let mut mock = MockHostBindings::new();
125        mock.expect_get_parent_ledger_hash()
126            .times(1)
127            .returning(|ptr, _| {
128                write_hash(ptr, 0xAB);
129                32
130            });
131        let _guard = setup_mock(mock);
132
133        let result = parent_ledger_hash();
134        assert!(result.is_ok());
135        assert_eq!(result.unwrap(), [0xAB; 32]);
136    }
137
138    #[test]
139    fn test_parent_ledger_hash_error() {
140        let mut mock = MockHostBindings::new();
141        mock.expect_get_parent_ledger_hash()
142            .times(1)
143            .returning(|_, _| INTERNAL_ERROR);
144        let _guard = setup_mock(mock);
145
146        assert!(parent_ledger_hash().is_err());
147    }
148
149    // ---- base_fee ----
150
151    #[test]
152    fn test_base_fee_success() {
153        let mut mock = MockHostBindings::new();
154        mock.expect_get_base_fee().times(1).returning(|ptr, _| {
155            write_u32(ptr, 12);
156            4
157        });
158        let _guard = setup_mock(mock);
159
160        let result = base_fee();
161        assert!(result.is_ok());
162        assert_eq!(result.unwrap(), 12);
163    }
164
165    #[test]
166    fn test_base_fee_error() {
167        let mut mock = MockHostBindings::new();
168        mock.expect_get_base_fee()
169            .times(1)
170            .returning(|_, _| INTERNAL_ERROR);
171        let _guard = setup_mock(mock);
172
173        assert!(base_fee().is_err());
174    }
175
176    // ---- amendment_enabled ----
177
178    #[test]
179    fn test_amendment_enabled_true() {
180        let mut mock = MockHostBindings::new();
181        mock.expect_amendment_enabled().times(1).returning(|_, _| 1);
182        let _guard = setup_mock(mock);
183
184        assert!(amendment_enabled(&[0u8; 32]).unwrap());
185    }
186
187    #[test]
188    fn test_amendment_enabled_false() {
189        let mut mock = MockHostBindings::new();
190        mock.expect_amendment_enabled().times(1).returning(|_, _| 0);
191        let _guard = setup_mock(mock);
192
193        assert!(!amendment_enabled(&[0u8; 32]).unwrap());
194    }
195
196    #[test]
197    fn test_amendment_enabled_error() {
198        let mut mock = MockHostBindings::new();
199        mock.expect_amendment_enabled()
200            .times(1)
201            .returning(|_, _| INTERNAL_ERROR);
202        let _guard = setup_mock(mock);
203
204        assert!(amendment_enabled(&[0u8; 32]).is_err());
205    }
206}