borsh_encoding.rs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // SPDX-License-Identifier: Apache-2.0
  2. use byte_slice_cast::AsByteSlice;
  3. use ethabi::{Param, ParamType};
  4. use num_bigint::{BigInt, Sign};
  5. use num_traits::ToPrimitive;
  6. use std::cmp::Ordering;
  7. /// This is the token that should be used for each function call in Solana runtime tests
  8. #[derive(Debug, PartialEq, Clone)]
  9. pub enum BorshToken {
  10. Address([u8; 32]),
  11. Int { width: u16, value: BigInt },
  12. Uint { width: u16, value: BigInt },
  13. FixedBytes(Vec<u8>),
  14. Bytes(Vec<u8>),
  15. Bool(bool),
  16. String(String),
  17. FixedArray(Vec<BorshToken>),
  18. Array(Vec<BorshToken>),
  19. Tuple(Vec<BorshToken>),
  20. }
  21. impl BorshToken {
  22. /// Encode the parameter into the buffer
  23. pub fn encode(&self, buffer: &mut Vec<u8>) {
  24. match self {
  25. BorshToken::Address(data) => {
  26. buffer.extend_from_slice(data);
  27. }
  28. BorshToken::Uint { width, value } => {
  29. encode_uint(*width, value, buffer);
  30. }
  31. BorshToken::Int { width, value } => {
  32. encode_int(*width, value, buffer);
  33. }
  34. BorshToken::FixedBytes(data) => {
  35. buffer.extend_from_slice(data);
  36. }
  37. BorshToken::Bytes(data) => {
  38. let len = data.len() as u32;
  39. buffer.extend_from_slice(&len.to_le_bytes());
  40. buffer.extend_from_slice(data);
  41. }
  42. BorshToken::Bool(value) => {
  43. buffer.push(*value as u8);
  44. }
  45. BorshToken::String(data) => {
  46. let len = data.len() as u32;
  47. buffer.extend_from_slice(&len.to_le_bytes());
  48. buffer.extend_from_slice(data.as_byte_slice());
  49. }
  50. BorshToken::Tuple(data) | BorshToken::FixedArray(data) => {
  51. for item in data {
  52. item.encode(buffer);
  53. }
  54. std::println!("len: {}", buffer.len());
  55. std::println!("buffer: {:?}", buffer);
  56. }
  57. BorshToken::Array(arr) => {
  58. let len = arr.len() as u32;
  59. buffer.extend_from_slice(&len.to_le_bytes());
  60. for item in arr {
  61. item.encode(buffer);
  62. }
  63. }
  64. }
  65. }
  66. pub fn into_string(self) -> Option<String> {
  67. match self {
  68. BorshToken::String(value) => Some(value),
  69. _ => None,
  70. }
  71. }
  72. pub fn into_array(self) -> Option<Vec<BorshToken>> {
  73. match self {
  74. BorshToken::Array(value) => Some(value),
  75. _ => None,
  76. }
  77. }
  78. pub fn into_fixed_bytes(self) -> Option<Vec<u8>> {
  79. match self {
  80. BorshToken::FixedBytes(value) => Some(value),
  81. _ => None,
  82. }
  83. }
  84. pub fn into_bytes(self) -> Option<Vec<u8>> {
  85. match self {
  86. BorshToken::Bytes(value) => Some(value),
  87. _ => None,
  88. }
  89. }
  90. pub fn into_bigint(self) -> Option<BigInt> {
  91. match self {
  92. BorshToken::Uint { value, .. } => Some(value),
  93. BorshToken::Int { value, .. } => Some(value),
  94. _ => None,
  95. }
  96. }
  97. }
  98. /// Encode a signed integer
  99. fn encode_int(width: u16, value: &BigInt, buffer: &mut Vec<u8>) {
  100. match width {
  101. 1..=8 => {
  102. let val = value.to_i8().unwrap();
  103. buffer.extend_from_slice(&val.to_le_bytes());
  104. }
  105. 9..=16 => {
  106. let val = value.to_i16().unwrap();
  107. buffer.extend_from_slice(&val.to_le_bytes());
  108. }
  109. 17..=32 => {
  110. let val = value.to_i32().unwrap();
  111. buffer.extend_from_slice(&val.to_le_bytes());
  112. }
  113. 33..=64 => {
  114. let val = value.to_i64().unwrap();
  115. buffer.extend_from_slice(&val.to_le_bytes());
  116. }
  117. 65..=128 => {
  118. let val = value.to_i128().unwrap();
  119. buffer.extend_from_slice(&val.to_le_bytes());
  120. }
  121. 129..=256 => {
  122. let mut val = value.to_signed_bytes_le();
  123. let byte_width = 32;
  124. match val.len().cmp(&byte_width) {
  125. Ordering::Greater => {
  126. while val.len() > byte_width {
  127. val.pop();
  128. }
  129. }
  130. Ordering::Less => {
  131. if value.sign() == Sign::Minus {
  132. val.extend(vec![255; byte_width - val.len()]);
  133. } else {
  134. val.extend(vec![0; byte_width - val.len()]);
  135. }
  136. }
  137. Ordering::Equal => (),
  138. }
  139. buffer.extend_from_slice(&val);
  140. }
  141. _ => unreachable!("bit width not supported"),
  142. }
  143. }
  144. /// Encode an unsigned integer
  145. fn encode_uint(width: u16, value: &BigInt, buffer: &mut Vec<u8>) {
  146. match width {
  147. 1..=8 => {
  148. let val = value.to_u8().unwrap();
  149. buffer.push(val);
  150. }
  151. 9..=16 => {
  152. let val = value.to_u16().unwrap();
  153. buffer.extend_from_slice(&val.to_le_bytes());
  154. }
  155. 17..=32 => {
  156. let val = value.to_u32().unwrap();
  157. buffer.extend_from_slice(&val.to_le_bytes());
  158. }
  159. 33..=64 => {
  160. let val = value.to_u64().unwrap();
  161. buffer.extend_from_slice(&val.to_le_bytes());
  162. }
  163. 65..=128 => {
  164. let val = value.to_u128().unwrap();
  165. buffer.extend_from_slice(&val.to_le_bytes());
  166. }
  167. 129..=256 => {
  168. let mut val = value.to_signed_bytes_le();
  169. let bytes_width = 32;
  170. match val.len().cmp(&bytes_width) {
  171. Ordering::Greater => {
  172. while val.len() > bytes_width {
  173. val.pop();
  174. }
  175. }
  176. Ordering::Less => {
  177. val.extend(vec![0; bytes_width - val.len()]);
  178. }
  179. Ordering::Equal => (),
  180. }
  181. buffer.extend_from_slice(&val);
  182. }
  183. _ => unreachable!("bit width not supported"),
  184. }
  185. }
  186. /// Decode the output buffer of a function given the description of its parameters
  187. pub fn decode_output(params: &[Param], data: &[u8]) -> Vec<BorshToken> {
  188. let mut offset: usize = 0;
  189. let mut decoded: Vec<BorshToken> = Vec::with_capacity(params.len());
  190. for item in params {
  191. let borsh_token = decode_at_offset(data, &mut offset, &item.kind);
  192. decoded.push(borsh_token);
  193. }
  194. decoded
  195. }
  196. /// Encode the arguments of a function
  197. pub fn encode_arguments(args: &[BorshToken]) -> Vec<u8> {
  198. let mut encoded: Vec<u8> = Vec::new();
  199. for item in args {
  200. item.encode(&mut encoded);
  201. }
  202. encoded
  203. }
  204. /// Decode a parameter at a given offset
  205. fn decode_at_offset(data: &[u8], offset: &mut usize, ty: &ParamType) -> BorshToken {
  206. match ty {
  207. ParamType::Address => {
  208. let read = &data[*offset..(*offset + 32)];
  209. (*offset) += 32;
  210. BorshToken::Address(<[u8; 32]>::try_from(read).unwrap())
  211. }
  212. ParamType::Uint(width) => {
  213. let decoding_width = width.next_power_of_two() / 8;
  214. let bigint =
  215. BigInt::from_bytes_le(Sign::Plus, &data[*offset..(*offset + decoding_width)]);
  216. (*offset) += decoding_width;
  217. BorshToken::Uint {
  218. width: *width as u16,
  219. value: bigint,
  220. }
  221. }
  222. ParamType::Int(width) => {
  223. let decoding_width = width.next_power_of_two() / 8;
  224. let bigint = BigInt::from_signed_bytes_le(&data[*offset..(*offset + decoding_width)]);
  225. (*offset) += decoding_width;
  226. BorshToken::Int {
  227. width: *width as u16,
  228. value: bigint,
  229. }
  230. }
  231. ParamType::Bool => {
  232. let val = data[*offset] == 1;
  233. (*offset) += 1;
  234. BorshToken::Bool(val)
  235. }
  236. ParamType::String => {
  237. let mut int_data: [u8; 4] = Default::default();
  238. int_data.copy_from_slice(&data[*offset..(*offset + 4)]);
  239. let len = u32::from_le_bytes(int_data) as usize;
  240. (*offset) += 4;
  241. let read_string = std::str::from_utf8(&data[*offset..(*offset + len)]).unwrap();
  242. (*offset) += len;
  243. BorshToken::String(read_string.to_string())
  244. }
  245. ParamType::FixedBytes(len) => {
  246. let read_data = &data[*offset..(*offset + len)];
  247. (*offset) += len;
  248. BorshToken::FixedBytes(read_data.to_vec())
  249. }
  250. ParamType::FixedArray(ty, len) => {
  251. let mut read_items: Vec<BorshToken> = Vec::with_capacity(*len);
  252. for _ in 0..*len {
  253. read_items.push(decode_at_offset(data, offset, ty));
  254. }
  255. BorshToken::FixedArray(read_items)
  256. }
  257. ParamType::Array(ty) => {
  258. let mut int_data: [u8; 4] = Default::default();
  259. int_data.copy_from_slice(&data[*offset..(*offset + 4)]);
  260. let len = u32::from_le_bytes(int_data);
  261. (*offset) += 4;
  262. let mut read_items: Vec<BorshToken> = Vec::with_capacity(len as usize);
  263. for _ in 0..len {
  264. read_items.push(decode_at_offset(data, offset, ty));
  265. }
  266. BorshToken::Array(read_items)
  267. }
  268. ParamType::Tuple(items) => {
  269. let mut read_items: Vec<BorshToken> = Vec::with_capacity(items.len());
  270. for item in items {
  271. read_items.push(decode_at_offset(data, offset, item));
  272. }
  273. BorshToken::Tuple(read_items)
  274. }
  275. ParamType::Bytes => {
  276. let mut int_data: [u8; 4] = Default::default();
  277. int_data.copy_from_slice(&data[*offset..(*offset + 4)]);
  278. let len = u32::from_le_bytes(int_data) as usize;
  279. (*offset) += 4;
  280. let read_data = &data[*offset..(*offset + len)];
  281. (*offset) += len;
  282. BorshToken::Bytes(read_data.to_vec())
  283. }
  284. }
  285. }