Skip to main content

neo_decompiler/nef/
types.rs

1use crate::util;
2
3use super::encoding::{encoded_method_tokens_size, varint_encoded_len};
4
5/// Parsed NEF header information.
6#[derive(Debug, Clone, PartialEq, Eq)]
7#[non_exhaustive]
8pub struct NefHeader {
9    /// Magic bytes at the start of the NEF container.
10    pub magic: [u8; 4],
11    /// Compiler identifier string (often includes tool name/version).
12    pub compiler: String,
13    /// Optional source string embedded in the container.
14    pub source: String,
15}
16
17/// Method token entry present in the NEF container.
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[non_exhaustive]
20pub struct MethodToken {
21    /// Script hash (little-endian bytes) for the called contract.
22    pub hash: [u8; 20],
23    /// Target method name.
24    pub method: String,
25    /// Declared parameter count.
26    pub parameters_count: u16,
27    /// Whether the method has a return value.
28    pub has_return_value: bool,
29    /// Call flags bitfield.
30    pub call_flags: u8,
31}
32
33/// Parsed NEF container.
34#[derive(Debug, Clone, PartialEq, Eq)]
35#[non_exhaustive]
36pub struct NefFile {
37    /// Header section.
38    pub header: NefHeader,
39    /// Method token table.
40    pub method_tokens: Vec<MethodToken>,
41    /// Script bytecode.
42    pub script: Vec<u8>,
43    /// Checksum stored in the container.
44    pub checksum: u32,
45}
46
47impl NefFile {
48    /// Length of the payload included in the checksum calculation.
49    #[must_use]
50    pub fn payload_len(&self) -> usize {
51        let fixed_header_len = super::FIXED_HEADER_SIZE; // magic + fixed 64-byte compiler
52        let source_bytes = self.header.source.as_bytes();
53        let source_len = varint_encoded_len(source_bytes.len() as u32) + source_bytes.len();
54        let tokens_len = encoded_method_tokens_size(&self.method_tokens);
55        let script_len = varint_encoded_len(self.script.len() as u32) + self.script.len();
56
57        fixed_header_len + source_len + 1 + tokens_len + 2 + script_len
58    }
59
60    /// Hash160 of the script (little-endian) as used for the contract script hash.
61    #[must_use]
62    pub fn script_hash(&self) -> [u8; 20] {
63        util::hash160(&self.script)
64    }
65
66    /// Hash160 of the script (little-endian) as used for the contract script hash.
67    #[must_use]
68    #[deprecated(
69        since = "0.5.1",
70        note = "use `script_hash()` instead, which is identical"
71    )]
72    pub fn script_hash_le(&self) -> [u8; 20] {
73        self.script_hash()
74    }
75
76    /// Script hash in big-endian form (for explorer comparisons).
77    #[must_use]
78    pub fn script_hash_be(&self) -> [u8; 20] {
79        let mut hash = self.script_hash();
80        hash.reverse();
81        hash
82    }
83}