pod_types/ledger/
calldata.rs

1use bytes::Bytes;
2use serde::{Deserialize, Serialize};
3
4use crate::{Hashable, Merkleizable, cryptography::merkle_tree::MerkleBuilder};
5
6#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, std::hash::Hash)]
7pub struct CallData(
8    #[serde(
9        serialize_with = "serialize_bytes_as_hex",
10        deserialize_with = "deserialize_bytes_as_hex"
11    )]
12    Bytes,
13);
14
15impl CallData {
16    /// Creates a new `CallData` instance, ensuring it has at least 4 bytes.
17    pub fn new(data: Bytes) -> Self {
18        // Calldata must have at least 4 bytes (first 4 bytes of keccak256 hash of function sig)
19        assert!(data.len() >= 4, "CallData must contain at least 4 bytes");
20        CallData(data)
21    }
22
23    // Get calldata as a slice
24    pub fn as_slice(&self) -> &[u8] {
25        &self.0[..]
26    }
27
28    // Get calldata as bytes
29    pub fn as_bytes(&self) -> &Bytes {
30        &self.0
31    }
32
33    pub fn empty() -> Self {
34        // Returns a `CallData` instance containing 1 zero byte.
35        CallData(Bytes::from(vec![]))
36    }
37
38    /// Converts the internal bytes to a hexadecimal string.
39    pub fn to_hex_string(&self) -> String {
40        let mut result = String::with_capacity(self.0.len() * 2);
41        for &byte in self.0.iter() {
42            result.push_str(&format!("{byte:02x}"));
43        }
44        result
45    }
46
47    /// Returns the first 4 bytes encoding the function to be called as an array
48    pub fn get_function_bytes(&self) -> [u8; 4] {
49        [self.0[0], self.0[1], self.0[2], self.0[3]]
50    }
51
52    /// Returns the calldata not including the function signature hash bytes
53    pub fn get_body(&self) -> &[u8] {
54        &self.0[4..]
55    }
56}
57
58impl Merkleizable for CallData {
59    fn append_leaves(&self, builder: &mut MerkleBuilder) {
60        builder.add_field("calldata", self.0.hash_custom());
61    }
62}
63
64fn serialize_bytes_as_hex<S>(data: &Bytes, serializer: S) -> Result<S::Ok, S::Error>
65where
66    S: serde::Serializer,
67{
68    // checks if serializer is human-readable or not
69    if serializer.is_human_readable() {
70        serializer.serialize_str(&hex::encode(data))
71    } else {
72        serializer.serialize_bytes(data)
73    }
74}
75
76// equivalently, deserialize according to human-readable or not
77fn deserialize_bytes_as_hex<'de, D>(deserializer: D) -> Result<Bytes, D::Error>
78where
79    D: serde::Deserializer<'de>,
80{
81    // check if deserializer human readable or not
82    if deserializer.is_human_readable() {
83        let s = String::deserialize(deserializer)?;
84        Ok(Bytes::from(
85            hex::decode(s).map_err(serde::de::Error::custom)?,
86        ))
87    } else {
88        Ok(Bytes::deserialize(deserializer)?)
89    }
90}