Skip to main content

muta_protocol/codec/
receipt.rs

1use std::convert::TryFrom;
2
3use bytes::Bytes;
4use prost::Message;
5
6use crate::{
7    codec::{primitive::Hash, CodecError, ProtocolCodecSync},
8    field, impl_default_bytes_codec_for,
9    types::primitive as protocol_primitive,
10    types::receipt as protocol_receipt,
11    ProtocolError, ProtocolResult,
12};
13
14// #####################
15// Protobuf
16// #####################
17
18#[derive(Clone, Message)]
19pub struct Receipt {
20    #[prost(message, tag = "1")]
21    pub state_root: Option<Hash>,
22
23    #[prost(uint64, tag = "2")]
24    pub epoch_id: u64,
25
26    #[prost(message, tag = "3")]
27    pub tx_hash: Option<Hash>,
28
29    #[prost(uint64, tag = "4")]
30    pub cycles_used: u64,
31
32    #[prost(message, repeated, tag = "5")]
33    pub events: Vec<Event>,
34
35    #[prost(message, tag = "6")]
36    pub response: Option<ReceiptResponse>,
37}
38
39#[derive(Clone, Message)]
40pub struct ReceiptResponse {
41    #[prost(bytes, tag = "1")]
42    pub service_name: Vec<u8>,
43
44    #[prost(bytes, tag = "2")]
45    pub method: Vec<u8>,
46
47    #[prost(bytes, tag = "3")]
48    pub ret: Vec<u8>,
49
50    #[prost(bool, tag = "4")]
51    pub is_error: bool,
52}
53
54#[derive(Clone, Message)]
55pub struct Event {
56    #[prost(bytes, tag = "1")]
57    pub service: Vec<u8>,
58
59    #[prost(bytes, tag = "2")]
60    pub data: Vec<u8>,
61}
62
63// #################
64// Conversion
65// #################
66
67// ReceiptResult
68
69impl From<receipt::ReceiptResponse> for ReceiptResponse {
70    fn from(response: receipt::ReceiptResponse) -> ReceiptResponse {
71        ReceiptResponse {
72            service_name: response.service_name.as_bytes().to_vec(),
73            method:       response.method.as_bytes().to_vec(),
74            ret:          response.ret.as_bytes().to_vec(),
75            is_error:     response.is_error,
76        }
77    }
78}
79
80impl TryFrom<ReceiptResponse> for receipt::ReceiptResponse {
81    type Error = ProtocolError;
82
83    fn try_from(response: ReceiptResponse) -> Result<receipt::ReceiptResponse, Self::Error> {
84        Ok(receipt::ReceiptResponse {
85            service_name: String::from_utf8(response.service_name)
86                .map_err(CodecError::FromStringUtf8)?,
87            method:       String::from_utf8(response.method).map_err(CodecError::FromStringUtf8)?,
88            ret:          String::from_utf8(response.ret).map_err(CodecError::FromStringUtf8)?,
89            is_error:     response.is_error,
90        })
91    }
92}
93
94// Receipt
95
96impl From<receipt::Receipt> for Receipt {
97    fn from(receipt: receipt::Receipt) -> Receipt {
98        let state_root = Some(Hash::from(receipt.state_root));
99        let tx_hash = Some(Hash::from(receipt.tx_hash));
100        let events = receipt.events.into_iter().map(Event::from).collect();
101        let response = Some(ReceiptResponse::from(receipt.response));
102
103        Receipt {
104            state_root,
105            epoch_id: receipt.epoch_id,
106            tx_hash,
107            cycles_used: receipt.cycles_used,
108            events,
109            response,
110        }
111    }
112}
113
114impl TryFrom<Receipt> for receipt::Receipt {
115    type Error = ProtocolError;
116
117    fn try_from(receipt: Receipt) -> Result<receipt::Receipt, Self::Error> {
118        let state_root = field!(receipt.state_root, "Receipt", "state_root")?;
119        let tx_hash = field!(receipt.tx_hash, "Receipt", "tx_hash")?;
120        let response = field!(receipt.response, "Receipt", "response")?;
121        let events = receipt
122            .events
123            .into_iter()
124            .map(protocol_receipt::Event::try_from)
125            .collect::<Result<Vec<protocol_receipt::Event>, ProtocolError>>()?;
126
127        let receipt = receipt::Receipt {
128            state_root: protocol_primitive::Hash::try_from(state_root)?,
129            epoch_id: receipt.epoch_id,
130            tx_hash: protocol_primitive::Hash::try_from(tx_hash)?,
131            cycles_used: receipt.cycles_used,
132            events,
133            response: receipt::ReceiptResponse::try_from(response)?,
134        };
135
136        Ok(receipt)
137    }
138}
139
140// Event
141impl From<receipt::Event> for Event {
142    fn from(event: receipt::Event) -> Event {
143        Event {
144            service: event.service.as_bytes().to_vec(),
145            data:    event.data.as_bytes().to_vec(),
146        }
147    }
148}
149
150impl TryFrom<Event> for receipt::Event {
151    type Error = ProtocolError;
152
153    fn try_from(event: Event) -> Result<receipt::Event, Self::Error> {
154        Ok(receipt::Event {
155            service: String::from_utf8(event.service).map_err(CodecError::FromStringUtf8)?,
156            data:    String::from_utf8(event.data).map_err(CodecError::FromStringUtf8)?,
157        })
158    }
159}
160
161// #################
162// Codec
163// #################
164
165impl_default_bytes_codec_for!(receipt, [Receipt]);