forest/lotus_json/
receipt.rs1use ::cid::Cid;
5use fvm_ipld_encoding::RawBytes;
6
7use super::*;
8use crate::shim::executor::Receipt;
9
10#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
11#[serde(rename_all = "PascalCase")]
12#[schemars(rename = "Receipt")]
13pub struct ReceiptLotusJson {
14 exit_code: u32,
15 #[schemars(with = "LotusJson<RawBytes>")]
16 #[serde(with = "crate::lotus_json")]
17 r#return: RawBytes,
18 gas_used: u64,
19 #[schemars(with = "LotusJson<Option<Cid>>")]
20 #[serde(with = "crate::lotus_json", default)] events_root: Option<Cid>,
22}
23
24impl HasLotusJson for Receipt {
25 type LotusJson = ReceiptLotusJson;
26
27 #[cfg(test)]
28 fn snapshots() -> Vec<(serde_json::Value, Self)> {
29 vec![
30 (
31 json!({
32 "ExitCode": 0,
33 "Return": "aGVsbG8gd29ybGQh",
34 "GasUsed": 0,
35 "EventsRoot": null,
36 }),
37 Self::V3(fvm_shared3::receipt::Receipt {
38 exit_code: fvm_shared3::error::ExitCode::new(0),
39 return_data: RawBytes::new(Vec::from_iter(*b"hello world!")),
40 gas_used: 0,
41 events_root: None,
42 }),
43 ),
44 (
45 json!({
46 "ExitCode": 0,
47 "Return": "aGVsbG8gd29ybGQh",
48 "GasUsed": 0,
49 "EventsRoot": {
50 "/": "baeaaaaa"
51 }
52 }),
53 Self::V3(fvm_shared3::receipt::Receipt {
54 exit_code: fvm_shared3::error::ExitCode::new(0),
55 return_data: RawBytes::new(Vec::from_iter(*b"hello world!")),
56 gas_used: 0,
57 events_root: Some(Cid::default()),
58 }),
59 ),
60 ]
61 }
62
63 fn into_lotus_json(self) -> Self::LotusJson {
64 Self::LotusJson {
65 exit_code: self.exit_code().value(),
66 r#return: self.return_data(),
67 gas_used: self.gas_used(),
68 events_root: self.events_root(),
69 }
70 }
71
72 fn from_lotus_json(lotus_json: Self::LotusJson) -> Self {
73 let Self::LotusJson {
74 exit_code,
75 r#return,
76 gas_used,
77 events_root,
78 } = lotus_json;
79 Self::V3(fvm_shared3::receipt::Receipt {
80 exit_code: fvm_shared3::error::ExitCode::new(exit_code),
81 return_data: r#return,
82 gas_used,
83 events_root,
84 })
85 }
86}
87
88#[test]
89fn shapshots() {
90 assert_all_snapshots::<Receipt>()
91}
92
93#[test]
101fn cannot_call_arbitrary_tests_on_receipt() {
102 use pretty_assertions::assert_eq;
103
104 let v2 = Receipt::V2(fvm_shared2::receipt::Receipt {
105 exit_code: fvm_shared2::error::ExitCode::new(0),
106 return_data: RawBytes::new(Vec::from_iter(*b"hello world!")),
107 gas_used: 0,
108 });
109 let v3 = Receipt::V3(fvm_shared3::receipt::Receipt {
110 exit_code: fvm_shared3::error::ExitCode::new(0),
111 return_data: RawBytes::new(Vec::from_iter(*b"hello world!")),
112 gas_used: 0,
113 events_root: None,
114 });
115 let json = json!({
116 "ExitCode": 0,
117 "Return": "aGVsbG8gd29ybGQh",
118 "GasUsed": 0,
119 "EventsRoot": null,
120 });
121
122 assert_eq!(
124 serde_json::to_value(v2.clone().into_lotus_json()).unwrap(),
125 json
126 );
127 assert_eq!(
128 serde_json::to_value(v3.clone().into_lotus_json()).unwrap(),
129 json
130 );
131
132 let deserialized = serde_json::from_value::<LotusJson<Receipt>>(json)
133 .unwrap()
134 .into_inner();
135 assert!(matches!(deserialized, Receipt::V3(_)));
136 assert_eq!(v3, deserialized);
137}