xrpl_wasm_stdlib/core/
chain.rs1use 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 #[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 #[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 #[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 #[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 #[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}