forest/message/
chain_message.rs1use super::*;
5use crate::message::signed_message::SignedMessage;
6use crate::shim::address::Protocol;
7use crate::shim::crypto::{SECP_SIG_LEN, Signature, SignatureType};
8use crate::shim::message::MethodNum;
9use crate::shim::{address::Address, econ::TokenAmount, message::Message};
10use ambassador::Delegate;
11use fvm_ipld_encoding::RawBytes;
12use get_size2::GetSize;
13use serde::{Deserialize, Serialize};
14use spire_enum::prelude::delegated_enum;
15use std::sync::Arc;
16
17#[delegated_enum]
20#[derive(
21 Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq, GetSize, derive_more::From, Delegate,
22)]
23#[delegate(MessageRead)]
24#[serde(untagged)]
25pub enum ChainMessage {
26 Unsigned(Arc<Message>),
27 Signed(Arc<SignedMessage>),
28}
29
30impl From<Message> for ChainMessage {
31 fn from(msg: Message) -> Self {
32 Arc::new(msg).into()
33 }
34}
35
36impl From<SignedMessage> for ChainMessage {
37 fn from(msg: SignedMessage) -> Self {
38 Arc::new(msg).into()
39 }
40}
41
42impl ChainMessage {
43 pub fn message(&self) -> &Message {
44 match self {
45 Self::Unsigned(m) => m,
46 Self::Signed(sm) => sm.message(),
47 }
48 }
49
50 pub fn cid(&self) -> cid::Cid {
51 delegate_chain_message!(self.cid())
52 }
53
54 pub fn equal_call(&self, other: &Self) -> bool {
60 self.message().equal_call(other.message())
61 }
62
63 pub fn for_gas_estimation(msg: Message, from_protocol: Protocol) -> Self {
70 match from_protocol {
71 Protocol::Secp256k1 => {
72 SignedMessage::new_unchecked(msg, Signature::new_secp256k1(vec![0; SECP_SIG_LEN]))
73 .into()
74 }
75 Protocol::Delegated => SignedMessage::new_unchecked(
77 msg,
78 Signature::new(SignatureType::Delegated, vec![0; SECP_SIG_LEN]),
79 )
80 .into(),
81 _ => msg.into(),
82 }
83 }
84}
85
86impl MessageReadWrite for ChainMessage {
87 fn set_gas_limit(&mut self, amount: u64) {
88 delegate_chain_message!(self => |i| Arc::make_mut(i).set_gas_limit(amount))
89 }
90
91 fn set_sequence(&mut self, sequence: u64) {
92 delegate_chain_message!(self => |i| Arc::make_mut(i).set_sequence(sequence))
93 }
94
95 fn set_gas_fee_cap(&mut self, cap: TokenAmount) {
96 delegate_chain_message!(self => |i| Arc::make_mut(i).set_gas_fee_cap(cap))
97 }
98
99 fn set_gas_premium(&mut self, prem: TokenAmount) {
100 delegate_chain_message!(self => |i| Arc::make_mut(i).set_gas_premium(prem))
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 fn dummy_msg() -> Message {
109 Message {
110 from: Address::new_id(2),
111 to: Address::new_id(1),
112 ..Default::default()
113 }
114 }
115
116 #[track_caller]
117 fn assert_signed_with_zero_sig(
118 chain_msg: ChainMessage,
119 sig_type: SignatureType,
120 msg: &Message,
121 ) {
122 let ChainMessage::Signed(signed) = chain_msg else {
123 panic!("expected Signed variant");
124 };
125 assert_eq!(signed.signature().signature_type(), sig_type);
126 assert_eq!(signed.signature().bytes(), &vec![0; SECP_SIG_LEN]);
127 assert_eq!(signed.message(), msg);
128 }
129
130 #[track_caller]
131 fn assert_unsigned(chain_msg: ChainMessage, msg: &Message) {
132 let ChainMessage::Unsigned(m) = chain_msg else {
133 panic!("expected Unsigned variant");
134 };
135 assert_eq!(&*m, msg);
136 }
137
138 #[test]
139 fn test_for_gas_estimation_secp256k1() {
140 let msg = dummy_msg();
141 let chain_msg = ChainMessage::for_gas_estimation(msg.clone(), Protocol::Secp256k1);
142 assert_signed_with_zero_sig(chain_msg, SignatureType::Secp256k1, &msg);
143 }
144
145 #[test]
146 fn test_for_gas_estimation_delegated() {
147 let msg = dummy_msg();
148 let chain_msg = ChainMessage::for_gas_estimation(msg.clone(), Protocol::Delegated);
149 assert_signed_with_zero_sig(chain_msg, SignatureType::Delegated, &msg);
152 }
153
154 #[test]
155 fn test_for_gas_estimation_bls() {
156 let msg = dummy_msg();
157 let chain_msg = ChainMessage::for_gas_estimation(msg.clone(), Protocol::BLS);
158 assert_unsigned(chain_msg, &msg);
161 }
162
163 #[test]
164 fn test_for_gas_estimation_id() {
165 let msg = dummy_msg();
166 let chain_msg = ChainMessage::for_gas_estimation(msg.clone(), Protocol::ID);
167 assert_unsigned(chain_msg, &msg);
168 }
169
170 #[test]
171 fn test_for_gas_estimation_actor() {
172 let msg = dummy_msg();
173 let chain_msg = ChainMessage::for_gas_estimation(msg.clone(), Protocol::Actor);
174 assert_unsigned(chain_msg, &msg);
175 }
176}