1pub mod chain_message;
5pub mod signed_message;
6
7use crate::shim::message::MethodNum;
8use crate::shim::{address::Address, econ::TokenAmount, message::Message as ShimMessage};
9use crate::shim::{gas::Gas, version::NetworkVersion};
10pub use chain_message::ChainMessage;
11use fvm_ipld_encoding::RawBytes;
12use num::Zero;
13pub use signed_message::SignedMessage;
14
15pub trait Message {
18 fn from(&self) -> Address;
20 fn to(&self) -> Address;
22 fn sequence(&self) -> u64;
24 fn value(&self) -> TokenAmount;
26 fn method_num(&self) -> MethodNum;
28 fn params(&self) -> &RawBytes;
30 fn set_gas_limit(&mut self, amount: u64);
32 fn set_sequence(&mut self, sequence: u64);
34 fn gas_limit(&self) -> u64;
36 fn required_funds(&self) -> TokenAmount;
38 fn gas_fee_cap(&self) -> TokenAmount;
40 fn gas_premium(&self) -> TokenAmount;
42 fn set_gas_fee_cap(&mut self, cap: TokenAmount);
44 fn set_gas_premium(&mut self, prem: TokenAmount);
46 fn effective_gas_premium(&self, base_fee: &TokenAmount) -> TokenAmount {
52 let available = self.gas_fee_cap() - base_fee;
53 available.clamp(TokenAmount::zero(), self.gas_premium())
56 }
57}
58
59impl Message for ShimMessage {
60 fn from(&self) -> Address {
61 self.from
62 }
63 fn to(&self) -> Address {
64 self.to
65 }
66 fn sequence(&self) -> u64 {
67 self.sequence
68 }
69 fn value(&self) -> TokenAmount {
70 self.value.clone()
71 }
72 fn method_num(&self) -> MethodNum {
73 self.method_num
74 }
75 fn params(&self) -> &RawBytes {
76 &self.params
77 }
78 fn gas_limit(&self) -> u64 {
79 self.gas_limit
80 }
81 fn set_gas_limit(&mut self, token_amount: u64) {
82 self.gas_limit = token_amount;
83 }
84 fn set_sequence(&mut self, new_sequence: u64) {
85 self.sequence = new_sequence;
86 }
87 fn required_funds(&self) -> TokenAmount {
88 &self.gas_fee_cap * self.gas_limit
89 }
90 fn gas_fee_cap(&self) -> TokenAmount {
91 self.gas_fee_cap.clone()
92 }
93 fn gas_premium(&self) -> TokenAmount {
94 self.gas_premium.clone()
95 }
96
97 fn set_gas_fee_cap(&mut self, cap: TokenAmount) {
98 self.gas_fee_cap = cap;
99 }
100
101 fn set_gas_premium(&mut self, prem: TokenAmount) {
102 self.gas_premium = prem;
103 }
104}
105
106pub fn valid_for_block_inclusion(
108 msg: &ShimMessage,
109 min_gas: Gas,
110 version: NetworkVersion,
111) -> Result<(), anyhow::Error> {
112 use crate::shim::address::ZERO_ADDRESS;
113 use crate::shim::econ::{BLOCK_GAS_LIMIT, TOTAL_FILECOIN};
114 if msg.version != 0 {
115 anyhow::bail!("Message version: {} not supported", msg.version);
116 }
117 if msg.to == *ZERO_ADDRESS && version >= NetworkVersion::V7 {
118 anyhow::bail!("invalid 'to' address");
119 }
120 if msg.value.is_negative() {
121 anyhow::bail!("message value cannot be negative");
122 }
123 if msg.value > *TOTAL_FILECOIN {
124 anyhow::bail!("message value cannot be greater than total FIL supply");
125 }
126 if msg.gas_fee_cap.is_negative() {
127 anyhow::bail!("gas_fee_cap cannot be negative");
128 }
129 if msg.gas_premium.is_negative() {
130 anyhow::bail!("gas_premium cannot be negative");
131 }
132 if msg.gas_premium > msg.gas_fee_cap {
133 anyhow::bail!("gas_fee_cap less than gas_premium");
134 }
135 if msg.gas_limit > BLOCK_GAS_LIMIT {
136 anyhow::bail!(
137 "gas_limit {} cannot be greater than block gas limit",
138 msg.gas_limit
139 );
140 }
141
142 if Gas::new(msg.gas_limit) < min_gas {
143 anyhow::bail!(
144 "gas_limit {} cannot be less than cost {} of storing a message on chain",
145 msg.gas_limit,
146 min_gas
147 );
148 }
149
150 Ok(())
151}
152
153#[cfg(test)]
154mod tests {
155 mod builder_test;
156}