fvm_shared/
message.rs

1// Copyright 2021-2023 Protocol Labs
2// Copyright 2019-2022 ChainSafe Systems
3// SPDX-License-Identifier: Apache-2.0, MIT
4
5use anyhow::anyhow;
6use fvm_ipld_encoding::RawBytes;
7use fvm_ipld_encoding::de::{Deserialize, Deserializer};
8use fvm_ipld_encoding::ser::{Serialize, Serializer};
9
10use crate::MethodNum;
11use crate::address::Address;
12use crate::econ::TokenAmount;
13
14/// Default Unsigned VM message type which includes all data needed for a state transition
15#[cfg_attr(feature = "testing", derive(Default))]
16#[derive(PartialEq, Clone, Debug, Hash, Eq)]
17pub struct Message {
18    pub version: u64,
19    pub from: Address,
20    pub to: Address,
21    pub sequence: u64,
22    pub value: TokenAmount,
23    pub method_num: MethodNum,
24    pub params: RawBytes,
25    pub gas_limit: u64,
26    pub gas_fee_cap: TokenAmount,
27    pub gas_premium: TokenAmount,
28}
29
30impl Message {
31    /// Does some basic checks on the Message to see if the fields are valid.
32    pub fn check(self: &Message) -> anyhow::Result<()> {
33        if self.gas_limit == 0 {
34            return Err(anyhow!("Message has no gas limit set"));
35        }
36        // TODO: max block limit?
37        if self.gas_limit > i64::MAX as u64 {
38            return Err(anyhow!("Message gas exceeds i64 max"));
39        }
40        Ok(())
41    }
42}
43
44impl Serialize for Message {
45    fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
46    where
47        S: Serializer,
48    {
49        (
50            &self.version,
51            &self.to,
52            &self.from,
53            &self.sequence,
54            &self.value,
55            &self.gas_limit,
56            &self.gas_fee_cap,
57            &self.gas_premium,
58            &self.method_num,
59            &self.params,
60        )
61            .serialize(s)
62    }
63}
64
65impl<'de> Deserialize<'de> for Message {
66    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
67    where
68        D: Deserializer<'de>,
69    {
70        let (
71            version,
72            to,
73            from,
74            sequence,
75            value,
76            gas_limit,
77            gas_fee_cap,
78            gas_premium,
79            method_num,
80            params,
81        ) = Deserialize::deserialize(deserializer)?;
82        Ok(Self {
83            version,
84            from,
85            to,
86            sequence,
87            value,
88            method_num,
89            params,
90            gas_limit,
91            gas_fee_cap,
92            gas_premium,
93        })
94    }
95}
96
97#[cfg(feature = "arb")]
98impl quickcheck::Arbitrary for Message {
99    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
100        Self {
101            to: Address::arbitrary(g),
102            from: Address::arbitrary(g),
103            version: u64::arbitrary(g),
104            sequence: u64::arbitrary(g),
105            value: TokenAmount::arbitrary(g),
106            method_num: u64::arbitrary(g),
107            params: fvm_ipld_encoding::RawBytes::new(Vec::arbitrary(g)),
108            gas_limit: u64::arbitrary(g),
109            gas_fee_cap: TokenAmount::arbitrary(g),
110            gas_premium: TokenAmount::arbitrary(g),
111        }
112    }
113}