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 From<Message> for Message_v2 {
138 fn from(other: Message) -> Self {
139 Self {
140 version: other.version as i64,
141 from: other.from.into(),
142 to: other.to.into(),
143 sequence: other.sequence,
144 value: other.value.into(),
145 method_num: other.method_num,
146 params: other.params,
147 gas_limit: other.gas_limit as i64,
148 gas_fee_cap: other.gas_fee_cap.into(),
149 gas_premium: other.gas_premium.into(),
150 }
151 }
152}
153
154impl From<&Message> for Message_v2 {
155 fn from(other: &Message) -> Self {
156 other.clone().into()
157 }
158}
159
160impl Message {
161 pub fn check(self: &Message) -> anyhow::Result<()> {
163 if self.gas_limit == 0 {
164 return Err(anyhow!("Message has no gas limit set"));
165 }
166 if self.gas_limit > i64::MAX as u64 {
167 return Err(anyhow!("Message gas exceeds i64 max"));
168 }
169 Ok(())
170 }
171
172 pub fn transfer(from: Address, to: Address, value: TokenAmount) -> Self {
174 Message {
175 from,
176 to,
177 value,
178 method_num: METHOD_SEND,
179 ..Default::default()
180 }
181 }
182
183 pub fn cid(&self) -> cid::Cid {
184 use crate::utils::cid::CidCborExt;
185 cid::Cid::from_cbor_blake2b256(self).expect("message serialization is infallible")
186 }
187
188 pub fn equal_call(&self, other: &Self) -> bool {
194 self.version == other.version
195 && self.from == other.from
196 && self.to == other.to
197 && self.sequence == other.sequence
198 && self.value == other.value
199 && self.method_num == other.method_num
200 && self.params == other.params
201 }
202}
203
204impl Serialize for Message {
205 fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
206 where
207 S: Serializer,
208 {
209 (
210 &self.version,
211 &self.to,
212 &self.from,
213 &self.sequence,
214 &self.value,
215 &self.gas_limit,
216 &self.gas_fee_cap,
217 &self.gas_premium,
218 &self.method_num,
219 &self.params,
220 )
221 .serialize(s)
222 }
223}
224
225impl<'de> Deserialize<'de> for Message {
226 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
227 where
228 D: Deserializer<'de>,
229 {
230 let (
231 version,
232 to,
233 from,
234 sequence,
235 value,
236 gas_limit,
237 gas_fee_cap,
238 gas_premium,
239 method_num,
240 params,
241 ) = Deserialize::deserialize(deserializer)?;
242 Ok(Self {
243 version,
244 from,
245 to,
246 sequence,
247 value,
248 method_num,
249 params,
250 gas_limit,
251 gas_fee_cap,
252 gas_premium,
253 })
254 }
255}