1use codec::{Decode, Encode};
2use scale_info::{
3 prelude::{boxed::Box, fmt::Debug, vec, vec::Vec},
4 TypeInfo,
5};
6
7#[cfg(feature = "runtime")]
8use scale_info::prelude::any::Any;
9
10#[cfg(feature = "runtime")]
11use primitive_types::U256;
12
13#[cfg(feature = "runtime")]
14use crate::Bytes;
15
16#[cfg(feature = "std")]
17use serde::{Deserialize, Serialize};
18
19#[cfg(feature = "runtime")]
20use sp_runtime::RuntimeString;
21
22#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
24#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
25pub enum Type {
26 Address(u16),
27 DynamicAddress,
28 Bool,
29 Int(u16),
30 Uint(u16),
31 Bytes(u8),
33 DynamicBytes,
34 String,
35 Enum(u8),
36 Struct(u8),
37 Mapping(Box<Type>, Box<Type>),
38 Contract,
39 Ref(Box<Type>),
40 Option(Box<Type>),
41 OptionalInsurance,
42 OptionalReward,
43 StorageRef(Box<Type>),
44 Value,
46 Slice,
48 Hasher(HasherAlgo, u16),
49 Crypto(CryptoAlgo),
50}
51
52#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
53#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
54pub enum HasherAlgo {
55 Blake2,
56 Keccak256,
57}
58
59#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
60#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
61pub enum CryptoAlgo {
62 Ed25519,
63 Sr25519,
64 Ecdsa,
65}
66
67#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
68#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
69pub struct GatewayABIConfig {
72 pub block_number_type_size: u16,
74 pub hash_size: u16,
76 pub hasher: HasherAlgo,
78 pub crypto: CryptoAlgo,
80 pub address_length: u16,
82 pub value_type_size: u16,
84 pub decimals: u16,
86 pub structs: Vec<StructDecl>,
88}
89
90impl Default for GatewayABIConfig {
91 fn default() -> GatewayABIConfig {
92 GatewayABIConfig {
93 block_number_type_size: 32,
94 hash_size: 32,
95 hasher: HasherAlgo::Blake2,
96 crypto: CryptoAlgo::Sr25519,
97 address_length: 32, value_type_size: 8, decimals: 8,
100 structs: vec![],
101 }
102 }
103}
104
105#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
106#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
107pub struct ContractActionDesc<Hash, TargetId, AccountId> {
108 pub action_id: Hash,
109 pub target_id: Option<TargetId>,
110 pub to: Option<AccountId>,
111}
112
113#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
114#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
115pub struct Parameter {
116 pub name: Option<Vec<u8>>,
118 pub ty: Type,
120 pub no: u32,
122 pub indexed: Option<bool>,
124}
125
126#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
127#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
128pub struct StructDecl {
129 pub name: Type,
131 pub fields: Vec<Parameter>,
133 pub offsets: Vec<u16>,
135}
136
137impl Type {
138 pub fn size_of(&self, gen: &GatewayABIConfig) -> Result<usize, &'static str> {
142 match self {
143 Type::Enum(_) => Ok(1),
144 Type::Bool => Ok(1),
145 Type::Contract | Type::Address(_) => Ok(gen.address_length as usize),
146 Type::Bytes(n) => Ok(*n as usize),
147 Type::Uint(n) | Type::Int(n) => Ok((n / 8).into()),
148 Type::Struct(n) => {
149 let struct_size = gen
150 .structs
151 .get(*n as usize)
152 .ok_or("Can't access requested struct from gateway genesis")?
153 .offsets
154 .last()
155 .cloned()
156 .unwrap_or(0);
157 Ok(struct_size.into())
158 },
159 Type::String | Type::DynamicBytes => Ok(4),
160 Type::Hasher(_hasher_alg, _hash_size) => Ok(gen.hash_size as usize),
161 _ => unimplemented!(),
162 }
163 }
164
165 pub fn to_string_bytes(&self) -> &[u8] {
166 match self {
167 Type::Enum(_) => b"enum",
168 Type::Bool => b"bool",
169 Type::Contract => b"contract",
170 Type::Address(_) => b"address",
171 Type::Bytes(_) => b"bytes",
172 Type::Uint(n) => match n {
173 32 => b"uint32",
174 64 => b"uint64",
175 128 => b"uint128",
176 _ => unimplemented!(),
177 },
178 Type::Int(n) => match n {
179 32 => b"int32",
180 64 => b"int64",
181 128 => b"int128",
182 _ => unimplemented!(),
183 },
184 Type::String => b"string",
185 Type::DynamicBytes => b"dynamic_bytes",
186 Type::DynamicAddress => b"dynamic_address",
187 Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
188 HasherAlgo::Blake2 => match hash_size {
189 128 => b"blake2_128",
190 256 => b"blake2_256",
191 _ => unimplemented!(),
192 },
193 HasherAlgo::Keccak256 => match hash_size {
194 256 => b"blake2_256",
195 _ => unimplemented!(),
196 },
197 },
198 Type::Crypto(crypto_alg) => match crypto_alg {
199 CryptoAlgo::Ed25519 => b"ed25519",
200 CryptoAlgo::Sr25519 => b"sr25519",
201 CryptoAlgo::Ecdsa => b"ecdsa",
202 },
203 _ => unimplemented!(),
204 }
205 }
206
207 #[cfg(feature = "runtime")]
208 pub fn to_string(&self) -> RuntimeString {
209 match self {
210 Type::Enum(_) => RuntimeString::from("enum"),
211 Type::Bool => RuntimeString::from("bool"),
212 Type::Contract => RuntimeString::from("contract"),
213 Type::Address(_) => RuntimeString::from("address"),
214 Type::Bytes(_) => RuntimeString::from("bytes"),
215 Type::Uint(n) => match n {
216 32 => RuntimeString::from("uint32"),
217 64 => RuntimeString::from("uint64"),
218 128 => RuntimeString::from("uint128"),
219 _ => unimplemented!(),
220 },
221 Type::Int(n) => match n {
222 32 => RuntimeString::from("int32"),
223 64 => RuntimeString::from("int64"),
224 128 => RuntimeString::from("int128"),
225 _ => unimplemented!(),
226 },
227 Type::String => RuntimeString::from("string"),
228 Type::DynamicBytes => RuntimeString::from("dynamic_bytes"),
229 Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
230 HasherAlgo::Blake2 => match hash_size {
231 128 => RuntimeString::from("blake2_128"),
232 256 => RuntimeString::from("blake2_256"),
233 _ => unimplemented!(),
234 },
235 HasherAlgo::Keccak256 => match hash_size {
236 256 => RuntimeString::from("blake2_256"),
237 _ => unimplemented!(),
238 },
239 },
240 Type::Crypto(crypto_alg) => match crypto_alg {
241 CryptoAlgo::Ed25519 => RuntimeString::from("ed25519"),
242 CryptoAlgo::Sr25519 => RuntimeString::from("sr25519"),
243 CryptoAlgo::Ecdsa => RuntimeString::from("ecdsa"),
244 },
245 _ => unimplemented!(),
246 }
247 }
248
249 #[cfg(feature = "runtime")]
251 pub fn eval_abi(
252 &self,
253 encoded_val: Vec<u8>,
254 gen: &GatewayABIConfig,
255 ) -> Result<Vec<u8>, &'static str> {
256 match self {
257 Type::Address(size) => match size {
258 20 => {
259 let res: [u8; 20] = decode_buf2val(encoded_val)?;
260 Ok(res.encode())
261 },
262 32 => {
263 let res: [u8; 32] = decode_buf2val(encoded_val)?;
264 Ok(res.encode())
265 },
266 _ => Err("Unknown Address size"),
267 },
268 Type::DynamicAddress => match gen.address_length {
269 20 => {
270 let res: [u8; 20] = decode_buf2val(encoded_val)?;
271 Ok(res.encode())
272 },
273 32 => {
274 let res: [u8; 32] = decode_buf2val(encoded_val)?;
275 Ok(res.encode())
276 },
277 _ => unimplemented!(),
278 },
279 Type::Bool => {
280 let res: bool = decode_buf2val(encoded_val)?;
281 Ok(res.encode())
282 },
283 Type::OptionalInsurance => {
284 match encoded_val.len() {
289 0 => Ok(encoded_val),
290 32 => {
291 let res: [u128; 2] = decode_buf2val(encoded_val)?;
292 Ok(res.encode())
293 },
294 _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
295 }
296 },
297 Type::Int(size) => match size {
298 32 => {
299 let res: i32 = decode_buf2val(encoded_val)?;
300 Ok(res.encode())
301 },
302 64 => {
303 let res: i64 = decode_buf2val(encoded_val)?;
304 Ok(res.encode())
305 },
306 128 => {
307 let res: i128 = decode_buf2val(encoded_val)?;
308 Ok(res.encode())
309 },
310 _ => Err("Unknown Uint size"),
311 },
312 Type::Uint(size) => match size {
313 32 => {
314 let res: u32 = decode_buf2val(encoded_val)?;
315 Ok(res.encode())
316 },
317 64 => {
318 let res: u64 = decode_buf2val(encoded_val)?;
319 Ok(res.encode())
320 },
321 128 => {
322 let res: u128 = decode_buf2val(encoded_val)?;
323 Ok(res.encode())
324 },
325 _ => Err("Unknown Uint size"),
326 },
327 Type::Bytes(_) => {
328 let res: Bytes = decode_buf2val(encoded_val)?;
329 Ok(res.to_vec())
330 },
331 Type::DynamicBytes => Ok(encoded_val),
332 Type::String => {
333 let res: RuntimeString = decode_buf2val(encoded_val)?;
334 Ok(res.encode())
335 },
336 Type::Value => {
337 match gen.value_type_size {
338 8 => {
339 let res: u64 = decode_buf2val::<u64>(encoded_val)?;
341 Ok(res.encode())
342 },
343 16 => {
344 let res: u128 = decode_buf2val::<u128>(encoded_val)?;
346 Ok(res.encode())
347 },
348 32 => {
349 let res: U256 = decode_buf2val::<U256>(encoded_val)?;
351 Ok(res.encode())
352 },
353 _ => unimplemented!(),
354 }
355 },
356 _ => unimplemented!(),
357 }
358 }
359
360 #[cfg(feature = "runtime")]
362 pub fn eval(
363 &self,
364 encoded_val: Vec<u8>,
365 ) -> Result<Box<dyn Any>, &'static str> {
367 match self {
368 Type::Address(size) => match size {
369 20 => {
370 let res: [u8; 20] = decode_buf2val(encoded_val)?;
371 Ok(Box::new(res))
372 },
373 32 => {
374 let res: [u8; 32] = decode_buf2val(encoded_val)?;
375 Ok(Box::new(res))
376 },
377 _ => Err("Unknown Address size"),
378 },
379 Type::DynamicAddress => {
380 let res: Vec<u8> = decode_buf2val(encoded_val)?;
381 Ok(Box::new(res))
382 },
383 Type::Bool => {
384 let res: bool = decode_buf2val(encoded_val)?;
385 Ok(Box::new(res))
386 },
387 Type::OptionalInsurance => {
388 match encoded_val.len() {
393 0 => Ok(Box::new(encoded_val)),
394 32 => {
395 let res: [u128; 2] = decode_buf2val(encoded_val)?;
396 Ok(Box::new(res))
397 },
398 _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
399 }
400 },
401 Type::Int(size) => match size {
402 32 => {
403 let res: i32 = decode_buf2val(encoded_val)?;
404 Ok(Box::new(res))
405 },
406 64 => {
407 let res: i64 = decode_buf2val(encoded_val)?;
408 Ok(Box::new(res))
409 },
410 128 => {
411 let res: i128 = decode_buf2val(encoded_val)?;
412 Ok(Box::new(res))
413 },
414 _ => Err("Unknown Uint size"),
415 },
416 Type::Uint(size) => match size {
417 32 => {
418 let res: u32 = decode_buf2val(encoded_val)?;
419 Ok(Box::new(res))
420 },
421 64 => {
422 let res: u64 = decode_buf2val(encoded_val)?;
423 Ok(Box::new(res))
424 },
425 128 => {
426 let res: u128 = decode_buf2val(encoded_val)?;
427 Ok(Box::new(res))
428 },
429 _ => Err("Unknown Uint size"),
430 },
431 Type::Bytes(_) => {
432 let res: Bytes = decode_buf2val(encoded_val)?;
433 Ok(Box::new(res))
434 },
435 Type::DynamicBytes => {
436 let res: Vec<u8> = decode_buf2val(encoded_val)?;
437 Ok(Box::new(res))
438 },
439 Type::String => {
440 let res: RuntimeString = decode_buf2val(encoded_val)?;
441 Ok(Box::new(res))
442 },
443 Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
444 HasherAlgo::Blake2 => match hash_size {
445 128 => Ok(Box::new(sp_io::hashing::blake2_128)),
446 256 => Ok(Box::new(sp_io::hashing::blake2_256)),
447 _ => unimplemented!(),
448 },
449 HasherAlgo::Keccak256 => match hash_size {
450 256 => Ok(Box::new(sp_io::hashing::keccak_256)),
451 _ => unimplemented!(),
452 },
453 },
454 _ => unimplemented!(),
455 }
456 }
457}
458
459pub fn eval_to_encoded(t: Type, raw_val: Vec<u8>) -> Result<Vec<u8>, &'static str> {
460 match t {
461 Type::Address(size) => match size {
462 20 => {
463 let res: [u8; 20] = decode_buf2val(raw_val)?;
464 Ok(res.to_vec())
465 },
466 32 => {
467 let res: [u8; 32] = decode_buf2val(raw_val)?;
468 Ok(res.to_vec())
469 },
470 _ => Err("Unknown Address size"),
471 },
472 Type::Uint(size) => match size {
473 32 => {
474 let res: u32 = decode_buf2val(raw_val)?;
475 Ok(res.encode())
476 },
477 64 => {
478 let res: u64 = decode_buf2val(raw_val)?;
479 Ok(res.encode())
480 },
481 128 => {
482 let res: u128 = decode_buf2val(raw_val)?;
483 Ok(res.encode())
484 },
485 _ => Err("Unknown Uint size"),
486 },
487 Type::OptionalInsurance => {
488 match raw_val.len() {
493 0 => Ok(raw_val),
494 32 => {
495 let res: [u128; 2] = decode_buf2val(raw_val)?;
496 Ok(res.encode())
497 },
498 _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
499 }
500 },
501 _ => Ok(vec![]),
502 }
503}
504
505#[cfg(feature = "runtime")]
506pub fn eval_trait_dynamically(t: Type) -> Result<Box<dyn Any>, &'static str> {
507 match t {
508 Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
509 HasherAlgo::Blake2 => match hash_size {
510 256 => Ok(Box::new(sp_runtime::traits::BlakeTwo256)),
511 _ => unimplemented!(),
512 },
513 HasherAlgo::Keccak256 => match hash_size {
514 256 => Ok(Box::new(sp_runtime::traits::Keccak256)),
515 _ => unimplemented!(),
516 },
517 },
518 _ => unimplemented!(),
519 }
520}
521
522pub fn from_bytes_string(bytes_string: &[u8]) -> Type {
523 match bytes_string {
524 b"bool" => Type::Bool,
525 b"contract" => Type::Contract,
526 b"address" => Type::Address(20),
527 b"dynamic_address" => Type::DynamicAddress,
528 b"bytes" => Type::DynamicBytes,
529 b"dynamic_bytes" => Type::DynamicBytes,
530 b"uint32" => Type::Uint(32),
531 b"uint64" => Type::Uint(64),
532 b"uint128" => Type::Uint(128),
533 b"int32" => Type::Uint(32),
534 b"int64" => Type::Uint(64),
535 b"int128" => Type::Uint(128),
536 b"string" => Type::String,
537 b"blake2_256" => Type::Hasher(HasherAlgo::Blake2, 256),
538 b"blake2_128" => Type::Hasher(HasherAlgo::Blake2, 128),
539 b"keccak256" => Type::Hasher(HasherAlgo::Keccak256, 128),
540 b"sr25519" => Type::Crypto(CryptoAlgo::Sr25519),
541 b"ed25519" => Type::Crypto(CryptoAlgo::Ed25519),
542 b"ecdsa" => Type::Crypto(CryptoAlgo::Ecdsa),
543 _ => unimplemented!(),
544 }
545}
546
547pub fn create_signature(
548 name_encoded: Vec<u8>,
549 args_abi: Vec<Type>,
550) -> Result<Vec<u8>, &'static str> {
551 const BEGIN_ARGS_CHAR: u8 = b'(';
552 const END_ARGS_CHAR: u8 = b')';
553 const COMMA_SEPARATOR: u8 = b',';
554
555 let name_bytes: &[u8] = name_encoded.as_slice();
556
557 let middle_args = args_abi
558 .iter()
559 .map(|t| t.to_string_bytes())
560 .collect::<Vec<&[u8]>>()
561 .as_slice()
562 .join(&COMMA_SEPARATOR);
563
564 let r = [
565 name_bytes,
566 &[BEGIN_ARGS_CHAR],
567 middle_args.as_slice(),
568 &[END_ARGS_CHAR],
569 ]
570 .concat();
571
572 Ok(r)
573}
574
575pub fn from_signature_to_abi(signature: Vec<u8>) -> Result<(Vec<u8>, Vec<Type>), &'static str> {
576 const BEGIN_ARGS_CHAR: u8 = b'(';
577 const END_ARGS_CHAR: u8 = b')';
578 const COMMA_SEPARATOR: u8 = b',';
579
580 let mut signature_iter = signature
581 .as_slice()
582 .split(|x| x.eq(&BEGIN_ARGS_CHAR) || x.eq(&COMMA_SEPARATOR) || x.eq(&END_ARGS_CHAR))
583 .filter(|&x| !x.is_empty());
584
585 let maybe_name = signature_iter.next().unwrap_or(&[]);
586
587 assert!(
588 !maybe_name.is_empty(),
589 "Can't find a name while reading event's ABI"
590 );
591
592 let types = signature_iter.map(from_bytes_string).collect::<Vec<Type>>();
593
594 Ok((maybe_name.to_vec(), types))
595}
596
597pub fn extract_property_names_from_signature_as_bytes(
598 signature: Vec<u8>,
599) -> Result<(Vec<u8>, Vec<Vec<u8>>), &'static str> {
600 const BEGIN_ARGS_CHAR: u8 = b'(';
601 const END_ARGS_CHAR: u8 = b')';
602 const COMMA_SEPARATOR: u8 = b',';
603
604 let mut signature_iter = signature
605 .as_slice()
606 .split(|x| x.eq(&BEGIN_ARGS_CHAR) || x.eq(&COMMA_SEPARATOR) || x.eq(&END_ARGS_CHAR))
607 .filter(|&x| !x.is_empty());
608
609 let maybe_name = signature_iter.next().unwrap_or(&[]);
610
611 assert!(
612 !maybe_name.is_empty(),
613 "Can't find a name while reading event's ABI"
614 );
615
616 let property_names = signature_iter
617 .map(|arg_candidate| arg_candidate.to_vec())
618 .collect::<Vec<Vec<u8>>>();
619
620 Ok((maybe_name.to_vec(), property_names))
621}
622
623pub fn decode_buf2val<D: Decode>(buf: Vec<u8>) -> Result<D, &'static str> {
624 D::decode(&mut &buf[..]).map_err(|_| "Decoding error: decode_buf2val")
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630 use std::string::String;
631
632 #[test]
633 fn successfully_creates_signature() {
634 let test_types_vec: Vec<Type> = vec![Type::Bytes(64), Type::Address(20), Type::Uint(64)];
635 let test_name = b"testName".to_vec();
636 let signature_bytes = create_signature(test_name, test_types_vec).unwrap();
637 let signature_string = String::from_utf8(signature_bytes).unwrap();
638
639 assert_eq!(signature_string, "testName(bytes,address,uint64)");
640 }
641
642 #[test]
643 fn successfully_interprets_signature_into_abi_types() {
644 let test_signature_bytes = b"testName(bytes,address,uint32)".to_vec();
645
646 let res = from_signature_to_abi(test_signature_bytes).unwrap();
647 assert_eq!(
648 (
649 b"testName".to_vec(),
650 vec![Type::DynamicBytes, Type::Address(20), Type::Uint(32),],
651 ),
652 res
653 );
654 }
655
656 #[test]
657 fn successfully_abi_evals_empty_insurance_and_reward_optional_insurance() {
658 let empty_bytes: Vec<u8> = vec![];
659 let res = eval_to_encoded(Type::OptionalInsurance, empty_bytes.clone());
660 assert_eq!(res, Ok(empty_bytes));
661 }
662
663 #[test]
664 fn successfully_abi_evals_valid_insurance_and_reward_optional_insurance() {
665 let valid_insurance_args_arr: [u128; 2] = [1, 2];
666 let res = eval_to_encoded(Type::OptionalInsurance, valid_insurance_args_arr.encode());
667 assert_eq!(
668 Ok(vec![
669 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
670 0, 0, 0, 0
671 ]),
672 res
673 );
674 }
675}