forest/message/
signed_message.rs1use super::Message as MessageTrait;
5use crate::eth::EthChainId;
6use crate::shim::message::MethodNum;
7use crate::shim::{
8 address::Address,
9 crypto::{Signature, SignatureType},
10 econ::TokenAmount,
11 message::Message,
12};
13use fvm_ipld_encoding::tuple::*;
14use fvm_ipld_encoding::{RawBytes, to_vec};
15use get_size2::GetSize;
16
17#[cfg_attr(test, derive(derive_quickcheck_arbitrary::Arbitrary))]
19#[derive(PartialEq, Clone, Debug, Serialize_tuple, Deserialize_tuple, Hash, Eq, GetSize)]
20pub struct SignedMessage {
21 pub message: Message,
22 pub signature: Signature,
23}
24
25impl SignedMessage {
26 pub fn new_from_parts(message: Message, signature: Signature) -> anyhow::Result<SignedMessage> {
29 signature.verify(&message.cid().to_bytes(), &message.from())?;
30 Ok(SignedMessage { message, signature })
31 }
32
33 pub fn new_unchecked(message: Message, signature: Signature) -> SignedMessage {
36 SignedMessage { message, signature }
37 }
38
39 pub fn message(&self) -> &Message {
41 &self.message
42 }
43
44 pub fn signature(&self) -> &Signature {
46 &self.signature
47 }
48
49 pub fn into_message(self) -> Message {
51 self.message
52 }
53
54 pub fn is_bls(&self) -> bool {
56 self.signature.signature_type() == SignatureType::Bls
57 }
58
59 pub fn is_secp256k1(&self) -> bool {
61 self.signature.signature_type() == SignatureType::Secp256k1
62 }
63
64 pub fn is_delegated(&self) -> bool {
66 self.signature.signature_type() == SignatureType::Delegated
67 }
68
69 pub fn verify(&self, eth_chain_id: EthChainId) -> anyhow::Result<()> {
71 self.signature
72 .authenticate_msg(eth_chain_id, self, &self.from())
73 }
74
75 pub fn cid(&self) -> cid::Cid {
79 if self.is_bls() {
80 self.message.cid()
81 } else {
82 use crate::utils::cid::CidCborExt;
83 cid::Cid::from_cbor_blake2b256(self).expect("message serialization is infallible")
84 }
85 }
86
87 pub fn chain_length(&self) -> anyhow::Result<usize> {
89 let serialized = match self.signature.signature_type() {
90 SignatureType::Bls => {
91 to_vec(&self.message)?
93 }
94 SignatureType::Secp256k1 | SignatureType::Delegated => {
95 to_vec(&self)?
97 }
98 };
99 Ok(serialized.len())
100 }
101
102 #[cfg(test)]
105 pub fn mock_bls_signed_message(message: Message) -> SignedMessage {
106 let signature = Signature::new_bls(vec![0; crate::shim::crypto::BLS_SIG_LEN]);
107 SignedMessage::new_unchecked(message, signature)
108 }
109}
110
111impl MessageTrait for SignedMessage {
112 fn from(&self) -> Address {
113 self.message.from()
114 }
115 fn to(&self) -> Address {
116 self.message.to()
117 }
118 fn sequence(&self) -> u64 {
119 self.message.sequence()
120 }
121 fn value(&self) -> TokenAmount {
122 self.message.value()
123 }
124 fn method_num(&self) -> MethodNum {
125 self.message.method_num
126 }
127 fn params(&self) -> &RawBytes {
128 self.message.params()
129 }
130 fn gas_limit(&self) -> u64 {
131 self.message.gas_limit()
132 }
133 fn set_gas_limit(&mut self, token_amount: u64) {
134 self.message.set_gas_limit(token_amount);
135 }
136 fn set_sequence(&mut self, new_sequence: u64) {
137 self.message.set_sequence(new_sequence);
138 }
139 fn required_funds(&self) -> TokenAmount {
140 self.message.required_funds()
141 }
142 fn gas_fee_cap(&self) -> TokenAmount {
143 self.message.gas_fee_cap()
144 }
145 fn gas_premium(&self) -> TokenAmount {
146 self.message.gas_premium()
147 }
148
149 fn set_gas_fee_cap(&mut self, cap: TokenAmount) {
150 self.message.set_gas_fee_cap(cap)
151 }
152
153 fn set_gas_premium(&mut self, prem: TokenAmount) {
154 self.message.set_gas_premium(prem)
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::shim::{address::Address, crypto::Signature, message::Message};
162 use fvm_ipld_encoding::to_vec;
163
164 #[test]
165 fn test_chain_length() {
166 let message = Message {
167 to: Address::new_id(1),
168 from: Address::new_id(2),
169 ..Message::default()
170 };
171
172 let bls_sig = Signature::new_bls(vec![0; 96]);
174 let signed_message_bls = SignedMessage::new_unchecked(message.clone(), bls_sig);
175 assert_eq!(
176 signed_message_bls.chain_length().unwrap(),
177 to_vec(&message).unwrap().len()
178 );
179
180 let secp_sig = Signature::new_secp256k1(vec![0; 65]);
182 let signed_message_secp = SignedMessage::new_unchecked(message.clone(), secp_sig);
183 assert_eq!(
184 signed_message_secp.chain_length().unwrap(),
185 to_vec(&signed_message_secp).unwrap().len()
186 );
187 }
188}