1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::avm::parser::credential_parser::credential_parser;
use crate::avm::parser::Context;
use crate::pvm::parser::add_delegator_tx::add_delegator_tx_parser;
use crate::pvm::parser::add_subnet_validator_tx::add_subnet_validator_tx_parser;
use crate::pvm::parser::add_validator_tx::add_validator_tx_parser;
use crate::pvm::parser::advance_time_tx_parser::advance_time_tx_parser;
use crate::pvm::parser::block_parser::BlockData;
use crate::pvm::parser::create_blockchain_tx::create_blockchain_tx_parser;
use crate::pvm::parser::create_subnet_tx::create_subnet_tx_parser;
use crate::pvm::parser::export_tx_parser::export_tx_parser;
use crate::pvm::parser::import_tx::import_tx_parser;
use crate::pvm::parser::reward_validator_tx_parser::reward_validator_parser;
use crate::utils::cb58::encode;
use crate::utils::conversion::{pop_i32, pop_i64, pop_u32};
use crate::utils::misc::generate_id;
use rust_base58::ToBase58;
use std::borrow::Borrow;
use std::error::Error;
use tracing::{instrument, trace};

#[instrument(fields(block_id = % _context.tx_id, block_type = "proposal"))]
pub fn proposal_block_parser(
    _raw_msg: &mut Vec<u8>,
    _context: &mut Context,
) -> Result<BlockData, Box<dyn Error>> {
    let parent_block_id = encode(&_raw_msg[*_context.offset..=(*_context.offset + 31)]).to_base58();
    trace!("Parent block id : {:?}", parent_block_id);

    *_context.offset += 32;

    let height = pop_i64(_raw_msg[*_context.offset..=(*_context.offset + 7)].borrow());
    trace!("height : {:?}", height);

    *_context.offset += 8;

    let tx_type_id = pop_i32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
    trace!("tx_type_id : {:?}", tx_type_id);

    let transaction;

    // Here to get the correct Tx ID we need to perform a small manipulation onto the _raw_msg .
    // In short in the bytes we get out of the socket , we have :
    // - 2B CODEC
    // - 4B TYPE OF BLOCK
    // - 32B PARENT BLOCK ID
    // - 8B HEIGHT of block
    // - 4B TYPE OF TX
    // - XB THE TX DATA
    // BUT we need to have the codec version added in between HEIGHT anf TYPE OF TX .
    _raw_msg.insert(*_context.offset, 0);
    _raw_msg.insert(*_context.offset, 0);
    let tx_id = generate_id(&_raw_msg[*_context.offset..=(_raw_msg.len() - 1)]);

    trace!("tx_id : {:?}", tx_id);

    match tx_type_id {
        12 => transaction = Some(add_validator_tx_parser(_raw_msg, tx_id, _context)?),
        13 => transaction = Some(add_subnet_validator_tx_parser(_raw_msg, tx_id, _context)?),
        14 => transaction = Some(add_delegator_tx_parser(_raw_msg, tx_id, _context)?),
        15 => transaction = Some(create_blockchain_tx_parser(_raw_msg, tx_id, _context)?),
        16 => transaction = Some(create_subnet_tx_parser(_raw_msg, tx_id, _context)?),
        17 => transaction = Some(import_tx_parser(_raw_msg, tx_id, _context)?),
        18 => transaction = Some(export_tx_parser(_raw_msg, tx_id, _context)?),
        19 => transaction = Some(advance_time_tx_parser(_raw_msg, tx_id, _context)?),
        20 => transaction = Some(reward_validator_parser(_raw_msg, tx_id, _context)?),
        _ => panic!(
            "This tx type is incorrect or not yet supported {}",
            tx_type_id
        ),
    }

    // Number of credentials
    let number_of_credentials: u32 =
        pop_u32(_raw_msg[*_context.offset..=(*_context.offset + 3)].borrow());
    trace!("Credential number : {:?}", number_of_credentials);
    *_context.offset += 4;

    // Credentials
    let mut index = 0;
    let mut credentials = Vec::new();
    while index < number_of_credentials {
        trace!("Credential number {}", index);
        let credential = credential_parser(&_raw_msg, _context)?;
        credentials.push(credential);
        index += 1;
    }

    let mut transactions = Vec::new();
    transactions.push(transaction);

    Ok(BlockData {
        type_id: 0,
        parent_block_id,
        height,
        transactions,
        credentials,
    })
}