1use anyhow::anyhow;
5use fvm_ipld_encoding::{RawBytes, de::Deserializer, ser::Serializer};
6use fvm_shared2::message::Message as Message_v2;
7pub use fvm_shared3::METHOD_SEND;
8pub use fvm_shared3::message::Message as Message_v3;
9use fvm_shared4::message::Message as Message_v4;
10use get_size2::GetSize;
11use serde::{Deserialize, Serialize};
12
13use crate::shim::{address::Address, econ::TokenAmount};
14use crate::utils::get_size::raw_bytes_heap_size_helper;
15
16pub type MethodNum = u64;
18
19#[derive(Clone, Default, PartialEq, Eq, Debug, Hash, GetSize)]
20#[cfg_attr(test, derive(derive_quickcheck_arbitrary::Arbitrary))]
21pub struct Message {
22 pub version: u64,
23 pub from: Address,
24 pub to: Address,
25 pub sequence: u64,
26 pub value: TokenAmount,
27 pub method_num: MethodNum,
28 #[cfg_attr(test, arbitrary(gen(
29 |g| RawBytes::new(Vec::arbitrary(g))
30 )))]
31 #[get_size(size_fn = raw_bytes_heap_size_helper)]
32 pub params: RawBytes,
33 pub gas_limit: u64,
34 pub gas_fee_cap: TokenAmount,
35 pub gas_premium: TokenAmount,
36}
37
38impl From<Message_v4> for Message {
39 fn from(other: Message_v4) -> Self {
40 Self {
41 version: other.version,
42 from: other.from.into(),
43 to: other.to.into(),
44 sequence: other.sequence,
45 value: other.value.into(),
46 method_num: other.method_num,
47 params: other.params,
48 gas_limit: other.gas_limit,
49 gas_fee_cap: other.gas_fee_cap.into(),
50 gas_premium: other.gas_premium.into(),
51 }
52 }
53}
54
55impl From<Message> for Message_v4 {
56 fn from(other: Message) -> Self {
57 (&other).into()
58 }
59}
60
61impl From<&Message> for Message_v4 {
62 fn from(other: &Message) -> Self {
63 let other: Message = other.clone();
64 Self {
65 version: other.version,
66 from: other.from.into(),
67 to: other.to.into(),
68 sequence: other.sequence,
69 value: other.value.into(),
70 method_num: other.method_num,
71 params: other.params,
72 gas_limit: other.gas_limit,
73 gas_fee_cap: other.gas_fee_cap.into(),
74 gas_premium: other.gas_premium.into(),
75 }
76 }
77}
78
79impl From<Message_v3> for Message {
80 fn from(other: Message_v3) -> Self {
81 Self {
82 version: other.version,
83 from: other.from.into(),
84 to: other.to.into(),
85 sequence: other.sequence,
86 value: other.value.into(),
87 method_num: other.method_num,
88 params: other.params,
89 gas_limit: other.gas_limit,
90 gas_fee_cap: other.gas_fee_cap.into(),
91 gas_premium: other.gas_premium.into(),
92 }
93 }
94}
95
96impl From<Message> for Message_v3 {
97 fn from(other: Message) -> Self {
98 (&other).into()
99 }
100}
101
102impl From<&Message> for Message_v3 {
103 fn from(other: &Message) -> Self {
104 let other: Message = other.clone();
105 Self {
106 version: other.version,
107 from: other.from.into(),
108 to: other.to.into(),
109 sequence: other.sequence,
110 value: other.value.into(),
111 method_num: other.method_num,
112 params: other.params,
113 gas_limit: other.gas_limit,
114 gas_fee_cap: other.gas_fee_cap.into(),
115 gas_premium: other.gas_premium.into(),
116 }
117 }
118}
119
120impl From<Message_v2> for Message {
121 fn from(other: Message_v2) -> Self {
122 Self {
123 version: other.version as u64,
124 from: other.from.into(),
125 to: other.to.into(),
126 sequence: other.sequence,
127 value: other.value.into(),
128 method_num: other.method_num,
129 params: other.params,
130 gas_limit: other.gas_limit as u64,
131 gas_fee_cap: other.gas_fee_cap.into(),
132 gas_premium: other.gas_premium.into(),
133 }
134 }
135}
136
137impl TryFrom<Message> for Message_v2 {
139 type Error = anyhow::Error;
140
141 fn try_from(other: Message) -> Result<Self, Self::Error> {
142 Ok(Self {
143 version: other.version as i64,
144 from: other.from.try_to_v2()?,
145 to: other.to.try_to_v2()?,
146 sequence: other.sequence,
147 value: other.value.into(),
148 method_num: other.method_num,
149 params: other.params,
150 gas_limit: other.gas_limit as i64,
151 gas_fee_cap: other.gas_fee_cap.into(),
152 gas_premium: other.gas_premium.into(),
153 })
154 }
155}
156
157impl TryFrom<&Message> for Message_v2 {
158 type Error = anyhow::Error;
159
160 fn try_from(other: &Message) -> Result<Self, Self::Error> {
161 other.clone().try_into()
162 }
163}
164
165impl Message {
166 pub fn check(self: &Message) -> anyhow::Result<()> {
168 if self.gas_limit == 0 {
169 return Err(anyhow!("Message has no gas limit set"));
170 }
171 if self.gas_limit > i64::MAX as u64 {
172 return Err(anyhow!("Message gas exceeds i64 max"));
173 }
174 Ok(())
175 }
176
177 pub fn transfer(from: Address, to: Address, value: TokenAmount) -> Self {
179 Message {
180 from,
181 to,
182 value,
183 method_num: METHOD_SEND,
184 ..Default::default()
185 }
186 }
187
188 pub fn cid(&self) -> cid::Cid {
189 use crate::utils::cid::CidCborExt;
190 cid::Cid::from_cbor_blake2b256(self).expect("message serialization is infallible")
191 }
192
193 pub fn equal_call(&self, other: &Self) -> bool {
199 self.version == other.version
200 && self.from == other.from
201 && self.to == other.to
202 && self.sequence == other.sequence
203 && self.value == other.value
204 && self.method_num == other.method_num
205 && self.params == other.params
206 }
207}
208
209impl Serialize for Message {
210 fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
211 where
212 S: Serializer,
213 {
214 (
215 &self.version,
216 &self.to,
217 &self.from,
218 &self.sequence,
219 &self.value,
220 &self.gas_limit,
221 &self.gas_fee_cap,
222 &self.gas_premium,
223 &self.method_num,
224 &self.params,
225 )
226 .serialize(s)
227 }
228}
229
230impl<'de> Deserialize<'de> for Message {
231 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
232 where
233 D: Deserializer<'de>,
234 {
235 let (
236 version,
237 to,
238 from,
239 sequence,
240 value,
241 gas_limit,
242 gas_fee_cap,
243 gas_premium,
244 method_num,
245 params,
246 ) = Deserialize::deserialize(deserializer)?;
247 Ok(Self {
248 version,
249 from,
250 to,
251 sequence,
252 value,
253 method_num,
254 params,
255 gas_limit,
256 gas_fee_cap,
257 gas_premium,
258 })
259 }
260}