1use darkfi_serial::{Decodable, Encodable};
20use std::io::Cursor;
21
22use crate::{
23 error::{ContractError, GenericResult},
24 tx::TransactionHash,
25};
26
27pub fn set_return_data(data: &[u8]) -> Result<(), ContractError> {
30 match u32::try_from(data.len()) {
32 Ok(len) => unsafe {
33 match set_return_data_(data.as_ptr(), len) {
34 0 => Ok(()),
35 errcode => Err(ContractError::from(errcode)),
36 }
37 },
38 Err(_) => Err(ContractError::DataTooLarge),
39 }
40}
41
42pub fn get_object_bytes(data: &mut [u8], object_index: u32) -> i64 {
44 unsafe { get_object_bytes_(data.as_mut_ptr(), object_index) }
45}
46
47pub fn get_object_size(object_index: u32) -> i64 {
49 unsafe { get_object_size_(object_index) }
50}
51
52pub(crate) fn parse_ret(ret: i64) -> GenericResult<Option<Vec<u8>>> {
56 if ret < 0 {
58 if ret == crate::error::DB_GET_EMPTY {
60 return Ok(None)
61 }
62
63 return Err(ContractError::from(ret))
64 }
65
66 let obj = match u32::try_from(ret) {
70 Ok(obj) => obj,
71 Err(_) => return Err(ContractError::SetRetvalError),
72 };
73 let obj_size = get_object_size(obj);
74 let mut buf = vec![0u8; obj_size as usize];
75 get_object_bytes(&mut buf, obj);
76
77 Ok(Some(buf))
78}
79
80fn parse_retval_u32(ret: i64) -> GenericResult<u32> {
81 if ret < 0 {
82 return Err(ContractError::from(ret))
83 }
84 assert!(ret >= 0);
85 let obj = ret as u32;
87 Ok(obj)
88}
89
90pub fn get_verifying_block_height() -> GenericResult<u32> {
97 let ret = unsafe { get_verifying_block_height_() };
98 parse_retval_u32(ret)
99}
100
101pub fn get_block_target() -> GenericResult<u32> {
108 let ret = unsafe { get_block_target_() };
109 parse_retval_u32(ret)
110}
111
112pub fn get_tx_hash() -> GenericResult<TransactionHash> {
119 let ret = unsafe { get_tx_hash_() };
120 let obj = parse_retval_u32(ret)?;
121 let mut tx_hash_data = [0u8; 32];
122 assert_eq!(get_object_size(obj), 32);
123 get_object_bytes(&mut tx_hash_data, obj);
124 Ok(TransactionHash(tx_hash_data))
125}
126
127pub fn get_call_index() -> GenericResult<u8> {
134 let ret = unsafe { get_call_index_() };
135 if ret < 0 {
136 return Err(ContractError::from(ret))
137 }
138 assert!(ret >= 0);
139 let obj = ret as u8;
141 Ok(obj)
142}
143
144pub fn get_blockchain_time() -> GenericResult<Option<Vec<u8>>> {
150 let ret = unsafe { get_blockchain_time_() };
151 parse_ret(ret)
152}
153
154pub fn get_last_block_height() -> GenericResult<Option<Vec<u8>>> {
160 let ret = unsafe { get_last_block_height_() };
161 parse_ret(ret)
162}
163
164pub fn get_tx(hash: &TransactionHash) -> GenericResult<Option<Vec<u8>>> {
172 let mut buf = vec![];
173 hash.encode(&mut buf)?;
174
175 let ret = unsafe { get_tx_(buf.as_ptr()) };
176 parse_ret(ret)
177}
178
179pub fn get_tx_location(hash: &TransactionHash) -> GenericResult<(u32, u16)> {
186 let mut buf = vec![];
187 hash.encode(&mut buf)?;
188
189 let ret = unsafe { get_tx_location_(buf.as_ptr()) };
190 let loc_data = parse_ret(ret)?.ok_or(ContractError::DbGetFailed)?;
191 let mut cursor = Cursor::new(loc_data);
192 Ok((Decodable::decode(&mut cursor)?, Decodable::decode(&mut cursor)?))
193}
194
195extern "C" {
196 fn set_return_data_(ptr: *const u8, len: u32) -> i64;
197 fn get_object_bytes_(ptr: *const u8, len: u32) -> i64;
198 fn get_object_size_(len: u32) -> i64;
199
200 fn get_verifying_block_height_() -> i64;
201 fn get_block_target_() -> i64;
202 fn get_tx_hash_() -> i64;
203 fn get_call_index_() -> i64;
204 fn get_blockchain_time_() -> i64;
205 fn get_last_block_height_() -> i64;
206 fn get_tx_(ptr: *const u8) -> i64;
207 fn get_tx_location_(ptr: *const u8) -> i64;
208}