xrpl_common_stdlib/host/
chain.rs1use 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 #[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 #[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 #[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 #[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 #[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}