filecoin_signer/
api.rs

1use std::convert::TryFrom;
2
3use serde::{Deserialize, Serialize};
4
5use fvm_ipld_encoding::RawBytes;
6use fvm_shared::message::Message;
7
8use extras::init::ExecParamsAPI;
9use extras::{
10    message::MessageAPI, miner, multisig, paych, signed_message::ref_fvm::SignedMessage,
11    signed_message::SignedMessageAPI,
12};
13
14use crate::error::SignerError;
15
16#[derive(Deserialize, Serialize)]
17#[serde(untagged)]
18#[allow(clippy::large_enum_variant)]
19pub enum MessageParams {
20    MessageParamsSerialized(String),
21    #[serde(with = "ExecParamsAPI")]
22    ExecParams(fil_actor_init::ExecParams),
23    #[serde(with = "multisig::ConstructorParamsAPI")]
24    MultisigConstructorParams(fil_actor_multisig::ConstructorParams),
25    #[serde(with = "multisig::ProposeParamsAPI")]
26    ProposeParams(fil_actor_multisig::ProposeParams),
27    #[serde(with = "multisig::TxnIDParamsAPI")]
28    TxnIDParams(fil_actor_multisig::TxnIDParams),
29    #[serde(with = "multisig::AddSignerParamsAPI")]
30    AddSignerParams(fil_actor_multisig::AddSignerParams),
31    #[serde(with = "multisig::RemoveSignerParamsAPI")]
32    RemoveSignerParams(fil_actor_multisig::RemoveSignerParams),
33    #[serde(with = "multisig::SwapSignerParamsAPI")]
34    SwapSignerParams(fil_actor_multisig::SwapSignerParams),
35    #[serde(with = "multisig::ChangeNumApprovalsThresholdParamsAPI")]
36    ChangeNumApprovalsThresholdParams(fil_actor_multisig::ChangeNumApprovalsThresholdParams),
37    #[serde(with = "multisig::LockBalanceParamsAPI")]
38    LockBalanceParams(fil_actor_multisig::LockBalanceParams),
39    #[serde(with = "paych::ConstructorParamsAPI")]
40    PaychConstructorParams(fil_actor_paych::ConstructorParams),
41    #[serde(with = "paych::UpdateChannelStateParamsAPI")]
42    UpdateChannelStateParams(fil_actor_paych::UpdateChannelStateParams),
43    //#[serde(with = "miner::MinerConstructorParamsAPI")]
44    //MinerConstructorParams(fil_actor_miner::MinerConstructorParams),
45    #[serde(with = "miner::ChangeOwnerAddressParamsAPI")]
46    ChangeOwnerAddressParamsAPI(fil_actor_miner::ChangeOwnerAddressParams),
47    #[serde(with = "miner::ChangeWorkerAddressParamsAPI")]
48    ChangeWorkerAddressParams(fil_actor_miner::ChangeWorkerAddressParams),
49    #[serde(with = "miner::ChangePeerIDParamsAPI")]
50    ChangePeerIDParams(fil_actor_miner::ChangePeerIDParams),
51    //#[serde(with = "miner::ChangeMultiaddrsParamsAPI")]
52    //ChangeMultiaddrsParams(fil_actor_miner::ChangeMultiaddrsParams),
53    //ConfirmSectorProofsParams(fil_actor_miner::ConfirmSectorProofsParams),
54    //DeferredCronEventParams(fil_actor_miner::DeferredCronEventParams),
55    //SubmitWindowedPoStParams(fil_actor_miner::SubmitWindowedPoStParams),
56    //ProveCommitSectorParams(fil_actor_miner::ProveCommitSectorParams),
57    //CheckSectorProvenParams(fil_actor_miner::CheckSectorProvenParams),
58    //ExtendSectorExpirationParams(fil_actor_miner::ExtendSectorExpirationParams),
59    //TerminateSectorsParams(fil_actor_miner::TerminateSectorsParams),
60    //DeclareFaultsParams(fil_actor_miner::DeclareFaultsParams),
61    //DeclareFaultsRecoveredParams(fil_actor_miner::DeclareFaultsRecoveredParams),
62    //CompactPartitionsParams(fil_actor_miner::CompactPartitionsParams),
63    //CompactSectorNumbersParams(fil_actor_miner::CompactSectorNumbersParams),
64    //ReportConsensusFaultParams(fil_actor_miner::ReportConsensusFaultParams),
65    #[serde(with = "miner::WithdrawBalanceParamsAPI")]
66    WithdrawBalanceParams(fil_actor_miner::WithdrawBalanceParams),
67    //PreCommitSectorBatchParams(fil_actor_miner::PreCommitSectorBatchParams),
68    #[serde(with = "miner::ApplyRewardParamsAPI")]
69    ApplyRewardParams(fil_actor_miner::ApplyRewardParams),
70    //DisputeWindowedPoStParams(fil_actor_miner::DisputeWindowedPoStParams),
71    //ProveCommitAggregateParams(fil_actor_miner::ProveCommitAggregateParams),
72    //ProveReplicaUpdatesParams(fil_actor_miner::ProveReplicaUpdatesParams),
73}
74
75impl MessageParams {
76    pub fn serialize(self) -> Result<RawBytes, SignerError> {
77        let params_serialized = match self {
78            MessageParams::MessageParamsSerialized(params_string) => {
79                let params_bytes = base64::decode(&params_string)
80                    .map_err(|err| SignerError::GenericString(err.to_string()))?;
81                RawBytes::from(params_bytes)
82            }
83            MessageParams::ExecParams(params) => RawBytes::serialize(&params)
84                .map_err(|err| SignerError::GenericString(err.to_string()))?,
85            MessageParams::MultisigConstructorParams(params) => RawBytes::serialize(&params)
86                .map_err(|err| SignerError::GenericString(err.to_string()))?,
87            MessageParams::ProposeParams(params) => RawBytes::serialize(&params)
88                .map_err(|err| SignerError::GenericString(err.to_string()))?,
89            MessageParams::TxnIDParams(params) => RawBytes::serialize(&params)
90                .map_err(|err| SignerError::GenericString(err.to_string()))?,
91            MessageParams::AddSignerParams(params) => RawBytes::serialize(&params)
92                .map_err(|err| SignerError::GenericString(err.to_string()))?,
93            MessageParams::RemoveSignerParams(params) => RawBytes::serialize(&params)
94                .map_err(|err| SignerError::GenericString(err.to_string()))?,
95            MessageParams::SwapSignerParams(params) => RawBytes::serialize(&params)
96                .map_err(|err| SignerError::GenericString(err.to_string()))?,
97            MessageParams::ChangeNumApprovalsThresholdParams(params) => {
98                RawBytes::serialize(&params)
99                    .map_err(|err| SignerError::GenericString(err.to_string()))?
100            }
101            MessageParams::LockBalanceParams(params) => RawBytes::serialize(&params)
102                .map_err(|err| SignerError::GenericString(err.to_string()))?,
103            MessageParams::PaychConstructorParams(params) => RawBytes::serialize(&params)
104                .map_err(|err| SignerError::GenericString(err.to_string()))?,
105            MessageParams::UpdateChannelStateParams(params) => RawBytes::serialize(&params)
106                .map_err(|err| SignerError::GenericString(err.to_string()))?,
107            //MessageParams::MinerConstructorParams(params) => RawBytes::serialize(&params)
108            //    .map_err(|err| SignerError::GenericString(err.to_string()))?,
109            MessageParams::ChangeOwnerAddressParamsAPI(params) => RawBytes::serialize(&params)
110                .map_err(|err| SignerError::GenericString(err.to_string()))?,
111            MessageParams::ChangeWorkerAddressParams(params) => RawBytes::serialize(&params)
112                .map_err(|err| SignerError::GenericString(err.to_string()))?,
113            MessageParams::ChangePeerIDParams(params) => RawBytes::serialize(&params)
114                .map_err(|err| SignerError::GenericString(err.to_string()))?,
115            //MessageParams::ChangeMultiaddrsParams(params) => RawBytes::serialize(&params)
116            //    .map_err(|err| SignerError::GenericString(err.to_string()))?,
117            MessageParams::WithdrawBalanceParams(params) => RawBytes::serialize(&params)
118                .map_err(|err| SignerError::GenericString(err.to_string()))?,
119            MessageParams::ApplyRewardParams(params) => RawBytes::serialize(&params)
120                .map_err(|err| SignerError::GenericString(err.to_string()))?,
121        };
122
123        Ok(params_serialized)
124    }
125}
126
127/// Structure containing an `UnsignedMessageAPI` or a `SignedMessageAPI`
128#[derive(Deserialize, Serialize, Debug)]
129#[serde(untagged)]
130pub enum MessageTxAPI {
131    #[serde(with = "MessageAPI")]
132    Message(Message),
133    #[serde(with = "SignedMessageAPI")]
134    SignedMessage(SignedMessage),
135}
136
137#[derive(Deserialize, Serialize)]
138#[serde(untagged)]
139pub enum MessageTx {
140    Message(Message),
141    SignedMessage(SignedMessage),
142}
143
144impl From<MessageTx> for MessageTxAPI {
145    fn from(message_tx: MessageTx) -> MessageTxAPI {
146        match message_tx {
147            MessageTx::Message(msg) => MessageTxAPI::Message(msg),
148            MessageTx::SignedMessage(smsg) => MessageTxAPI::SignedMessage(smsg),
149        }
150    }
151}
152
153/// Create multisig message api structure
154#[cfg_attr(feature = "with-arbitrary", derive(arbitrary::Arbitrary))]
155#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
156pub struct CreateMultisigMessageAPI {
157    #[serde(alias = "From")]
158    pub from: String,
159    #[serde(alias = "Nonce")]
160    pub nonce: u64,
161    #[serde(alias = "Value")]
162    pub value: String,
163
164    #[serde(rename = "gaslimit")]
165    #[serde(alias = "gasLimit")]
166    #[serde(alias = "gas_limit")]
167    #[serde(alias = "GasLimit")]
168    pub gas_limit: i64,
169
170    #[serde(rename = "gasfeecap")]
171    #[serde(alias = "gasFeeCap")]
172    #[serde(alias = "gas_fee_cap")]
173    #[serde(alias = "GasFeeCap")]
174    pub gas_fee_cap: String,
175
176    #[serde(rename = "gaspremium")]
177    #[serde(alias = "gasPremium")]
178    #[serde(alias = "gas_premium")]
179    #[serde(alias = "GasPremium")]
180    pub gas_premium: String,
181
182    #[serde(alias = "Signers")]
183    #[serde(alias = "signers")]
184    pub signers: Vec<String>,
185
186    #[serde(alias = "Threshold")]
187    #[serde(alias = "threshold")]
188    pub threshold: i64,
189
190    #[serde(alias = "UnlockDuration")]
191    #[serde(alias = "unlock_duration")]
192    pub unlock_duration: i64,
193
194    #[serde(alias = "StartEpoch")]
195    #[serde(alias = "start_epoch")]
196    pub start_epoch: i64,
197}
198
199/// Proposal message api structure
200#[cfg_attr(feature = "with-arbitrary", derive(arbitrary::Arbitrary))]
201#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
202pub struct ProposalMessageParamsAPI {
203    #[serde(alias = "Requester")]
204    pub requester: String,
205
206    #[serde(alias = "To")]
207    pub to: String,
208
209    #[serde(alias = "Value")]
210    pub value: String,
211
212    #[serde(alias = "Method")]
213    pub method: u64,
214
215    #[serde(alias = "Params")]
216    pub params: String,
217}
218
219impl MessageTxAPI {
220    pub fn get_message(&self) -> Message {
221        match self {
222            MessageTxAPI::Message(message) => message.to_owned(),
223            MessageTxAPI::SignedMessage(signed_message) => signed_message.message.to_owned(),
224        }
225    }
226}
227
228/// Message structure with network parameter
229/// NOTES: we don't need anymore since Address removed set_network (https://github.com/filecoin-project/ref-fvm/issues/1678)
230pub struct MessageTxNetwork {
231    pub message_tx: MessageTxAPI,
232    pub testnet: bool,
233}
234
235impl TryFrom<MessageTxNetwork> for MessageTxAPI {
236    type Error = SignerError;
237
238    fn try_from(message_tx_network: MessageTxNetwork) -> Result<MessageTxAPI, Self::Error> {
239        match message_tx_network.message_tx {
240            MessageTxAPI::Message(message_tx) => {
241                let to_address: fvm_shared::address::Address = message_tx.to.to_owned();
242
243                let from_address: fvm_shared::address::Address = message_tx.from.to_owned();
244
245                let message_with_network = Message {
246                    to: to_address,
247                    from: from_address,
248                    ..message_tx
249                };
250
251                Ok(MessageTxAPI::Message(message_with_network))
252            }
253            MessageTxAPI::SignedMessage(message_tx) => {
254                let to_address: fvm_shared::address::Address = message_tx.message.to.to_owned();
255
256                let from_address: fvm_shared::address::Address = message_tx.message.from.to_owned();
257
258                let tmp = message_tx.message.clone();
259
260                let message_with_network = Message {
261                    to: to_address,
262                    from: from_address,
263                    ..tmp
264                };
265
266                let signed_message = SignedMessage {
267                    message: message_with_network,
268                    signature: message_tx.signature,
269                };
270
271                Ok(MessageTxAPI::SignedMessage(signed_message))
272            }
273        }
274    }
275}
276
277#[cfg(test)]
278mod tests {
279    use fvm_ipld_encoding::{from_slice, to_vec};
280    use hex::{decode, encode};
281
282    use crate::api::MessageTxAPI;
283
284    const EXAMPLE_UNSIGNED_MESSAGE: &str = r#"
285        {
286            "To": "f17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy",
287            "From": "f1xcbgdhkgkwht3hrrnui3jdopeejsoas2rujnkdi",
288            "Nonce": 1,
289            "Value": "100000",
290            "GasFeeCap": "1",
291            "GasPremium": "1",
292            "GasLimit": 25000,
293            "Method": 0,
294            "Params": ""
295        }"#;
296
297    const EXAMPLE_CBOR_DATA: &str =
298        "8a005501fd1d0f4dfcd7e99afcb99a8326b7dc459d32c6285501b882619d46558f3d9e316d11b48dcf211327025a0144000186a01961a84200014200010040";
299
300    //const EXAMPLE_CBOR_DATA_CONV: &str = "8a004300ec075501dfe49184d46adc8f89d44638beb45f78fcad259001401a000f4240430009c4430009c402581d845501dfe49184d46adc8f89d44638beb45f78fcad2590430003e80040";
301
302    #[test]
303    fn json_to_cbor() {
304        let message_api: MessageTxAPI =
305            serde_json::from_str(EXAMPLE_UNSIGNED_MESSAGE).expect("FIXME");
306
307        let message = match message_api {
308            MessageTxAPI::Message(msg) => msg,
309            _ => panic!("Shouldn't be SignedMessage"),
310        };
311
312        let message_cbor: Vec<u8> = to_vec(&message).expect("Cbor serialization failed");
313        let message_cbor_hex = encode(message_cbor);
314
315        assert_eq!(EXAMPLE_CBOR_DATA, message_cbor_hex)
316    }
317
318    #[test]
319    fn cbor_to_json() {
320        let cbor_buffer = decode(EXAMPLE_CBOR_DATA).expect("FIXME");
321
322        let message =
323            MessageTxAPI::Message(from_slice(&cbor_buffer).expect("could not decode cbor"));
324
325        let message_json =
326            serde_json::to_string_pretty(&message).expect("could not serialize as JSON");
327
328        const EXPECTED_MESSAGE_JSON: &str = r#"{
329  "From": "f1xcbgdhkgkwht3hrrnui3jdopeejsoas2rujnkdi",
330  "To": "f17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy",
331  "Nonce": 1,
332  "Value": "100000",
333  "Method": 0,
334  "Params": "",
335  "GasLimit": 25000,
336  "GasFeeCap": "1",
337  "GasPremium": "1"
338}"#;
339
340        assert_eq!(EXPECTED_MESSAGE_JSON, message_json)
341    }
342
343    #[test]
344    fn conversion_signed_messages() {
345        const EXAMPLE_SIGNED_MESSAGE: &str = r#"{
346  "Message": {
347    "From": "f1iuj7atowet37tsmeehwxfvyjv2pqhsnyvb6niay",
348    "To": "f14ole2akjiw5qizembmw6r2e6yvj5ygmxgczervy",
349    "Nonce": 37,
350    "Value": "1000000000000000",
351    "Method": 0,
352    "Params": "",
353    "GasLimit": 2101318,
354    "GasFeeCap": "1890700000",
355    "GasPremium": "150000"
356  },
357  "Signature": {
358    "Type": 1,
359    "Data": "f3w5IcXFvWpWEAFp9LOAzixIsPjkgVaFx5XwynXx2sgZJ57yLIHLJi8CepHwoYeaWfZTRRUucHPARhi6iE2qqgA="
360  }
361}"#;
362
363        let message_api: MessageTxAPI =
364            serde_json::from_str(EXAMPLE_SIGNED_MESSAGE).expect("FIXME");
365
366        let signed_message_json =
367            serde_json::to_string_pretty(&message_api).expect("could not serialize as JSON");
368
369        assert_eq!(EXAMPLE_SIGNED_MESSAGE, signed_message_json);
370    }
371}