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