Skip to main content

avalanche_rs/pvm/parser/
input_parser.rs

1use tracing::{instrument, trace};
2
3use std::borrow::Borrow;
4
5use std::error::Error;
6
7use crate::avm::parser::Context;
8use crate::pvm::parser::output_parser::StakeableLockedInput;
9use crate::utils::conversion::{pop_i32, pop_i64};
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct Input {
13    pub type_id: i32,
14    pub stakeable_locked_input: Option<StakeableLockedInput>,
15    pub secp256k_transfer_input: Option<SECP256KTransferInput>,
16}
17
18#[derive(Serialize, Deserialize, Debug)]
19pub struct SECP256KTransferInput {
20    pub type_id: i32,
21    pub amount: i64,
22    pub address_indices: Vec<i32>,
23}
24
25#[instrument(skip(_raw_msg), fields(tx_id = % _context.tx_id))]
26pub fn input_parser<'a>(
27    _raw_msg: &'a [u8],
28    _context: &mut Context,
29) -> Result<Input, Box<dyn Error>> {
30    // Type Id
31    let type_id = pop_i32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
32    trace!("Type Id -- {}", type_id);
33    *_context.offset += 4;
34
35    // It must be 5
36    let mut secp256k_transfer_input = None;
37    let mut stakeable_locked_input = None;
38    match type_id {
39        5 => secp256k_transfer_input = Some(secp256k1_transfer_input_parser(_raw_msg, _context)?),
40        21 => stakeable_locked_input = Some(stackeable_lockin_parser(_raw_msg, _context)?),
41        _ => {
42            panic!(
43                "This input type is incorrect or not yet supported {}",
44                type_id
45            )
46        }
47    }
48
49    Ok(Input {
50        type_id,
51        stakeable_locked_input,
52        secp256k_transfer_input,
53    })
54}
55
56#[instrument(skip(_raw_msg), fields(tx_id = % _context.tx_id))]
57pub fn secp256k1_transfer_input_parser<'a>(
58    _raw_msg: &'a [u8],
59    _context: &mut Context,
60) -> Result<SECP256KTransferInput, Box<dyn Error>> {
61    // Amount
62    let amount = pop_i64(_raw_msg[*_context.offset..=(*_context.offset + 7)].borrow());
63    trace!("Amount : {:?}", amount);
64    *_context.offset += 8;
65
66    // Number of addresses
67    let number_of_address = pop_i32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
68    trace!("Number of addresses : {:?}", number_of_address);
69    *_context.offset += 4;
70
71    // Addresses
72    let mut index = 0;
73    let mut address_indices = Vec::new();
74
75    while index < number_of_address {
76        let address_indice = pop_i32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
77        trace!("Addresses number {} {:?}", index, address_indice);
78        address_indices.push(address_indice);
79        *_context.offset += 4;
80        index += 1;
81    }
82
83    Ok(SECP256KTransferInput {
84        type_id: 5,
85        amount,
86        address_indices,
87    })
88}
89
90pub fn stackeable_lockin_parser<'a>(
91    _raw_msg: &'a [u8],
92    _context: &mut Context,
93) -> Result<StakeableLockedInput, Box<dyn Error>> {
94    // Amount
95    let locktime = pop_i64(_raw_msg[*_context.offset..=(*_context.offset + 7)].borrow());
96    trace!("Stack Locktime : {:?}", locktime);
97    *_context.offset += 8;
98
99    let type_id = pop_i32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
100    trace!("Type Id : {:?}", type_id);
101    *_context.offset += 4;
102
103    let input;
104
105    match type_id {
106        5 => input = secp256k1_transfer_input_parser(_raw_msg, _context)?,
107        _ => panic!(
108            "This input type is incorrect or not yet supported {}",
109            type_id
110        ),
111    }
112
113    Ok(StakeableLockedInput {
114        locktime,
115        asset_id: "".to_string(),
116        input,
117    })
118}