Skip to main content

muta_protocol/codec/
transaction.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    ProtocolError, ProtocolResult,
11};
12
13#[derive(Clone, Message)]
14pub struct TransactionRequest {
15    #[prost(bytes, tag = "1")]
16    pub service_name: Vec<u8>,
17
18    #[prost(bytes, tag = "2")]
19    pub method: Vec<u8>,
20
21    #[prost(bytes, tag = "3")]
22    pub payload: Vec<u8>,
23}
24
25#[derive(Clone, Message)]
26pub struct RawTransaction {
27    #[prost(message, tag = "1")]
28    pub chain_id: Option<Hash>,
29
30    #[prost(message, tag = "2")]
31    pub nonce: Option<Hash>,
32
33    #[prost(uint64, tag = "3")]
34    pub timeout: u64,
35
36    #[prost(uint64, tag = "4")]
37    pub cycles_price: u64,
38
39    #[prost(uint64, tag = "5")]
40    pub cycles_limit: u64,
41
42    #[prost(message, tag = "6")]
43    pub request: Option<TransactionRequest>,
44}
45
46#[derive(Clone, Message)]
47pub struct SignedTransaction {
48    #[prost(message, tag = "1")]
49    pub raw: Option<RawTransaction>,
50
51    #[prost(message, tag = "2")]
52    pub tx_hash: Option<Hash>,
53
54    #[prost(bytes, tag = "3")]
55    pub pubkey: Vec<u8>,
56
57    #[prost(bytes, tag = "4")]
58    pub signature: Vec<u8>,
59}
60
61// #################
62// Conversion
63// #################
64
65// TransactionAction
66
67impl From<transaction::TransactionRequest> for TransactionRequest {
68    fn from(request: transaction::TransactionRequest) -> TransactionRequest {
69        TransactionRequest {
70            service_name: request.service_name.as_bytes().to_vec(),
71            method:       request.method.as_bytes().to_vec(),
72            payload:      request.payload.as_bytes().to_vec(),
73        }
74    }
75}
76
77impl TryFrom<TransactionRequest> for transaction::TransactionRequest {
78    type Error = ProtocolError;
79
80    fn try_from(
81        request: TransactionRequest,
82    ) -> Result<transaction::TransactionRequest, Self::Error> {
83        Ok(transaction::TransactionRequest {
84            service_name: String::from_utf8(request.service_name)
85                .map_err(CodecError::FromStringUtf8)?,
86            method:       String::from_utf8(request.method).map_err(CodecError::FromStringUtf8)?,
87            payload:      String::from_utf8(request.payload).map_err(CodecError::FromStringUtf8)?,
88        })
89    }
90}
91
92// RawTransaction
93
94impl From<transaction::RawTransaction> for RawTransaction {
95    fn from(raw: transaction::RawTransaction) -> RawTransaction {
96        let chain_id = Some(Hash::from(raw.chain_id));
97        let nonce = Some(Hash::from(raw.nonce));
98        let request = Some(TransactionRequest::from(raw.request));
99
100        RawTransaction {
101            chain_id,
102            nonce,
103            cycles_price: raw.cycles_price,
104            timeout: raw.timeout,
105            cycles_limit: raw.cycles_limit,
106            request,
107        }
108    }
109}
110
111impl TryFrom<RawTransaction> for transaction::RawTransaction {
112    type Error = ProtocolError;
113
114    fn try_from(raw: RawTransaction) -> Result<transaction::RawTransaction, Self::Error> {
115        let chain_id = field!(raw.chain_id, "RawTransaction", "chain_id")?;
116        let nonce = field!(raw.nonce, "RawTransaction", "nonce")?;
117        let request = field!(raw.request, "RawTransaction", "request")?;
118
119        let raw_tx = transaction::RawTransaction {
120            chain_id:     protocol_primitive::Hash::try_from(chain_id)?,
121            nonce:        protocol_primitive::Hash::try_from(nonce)?,
122            timeout:      raw.timeout,
123            cycles_price: raw.cycles_price,
124            cycles_limit: raw.cycles_limit,
125            request:      transaction::TransactionRequest::try_from(request)?,
126        };
127
128        Ok(raw_tx)
129    }
130}
131
132// SignedTransaction
133
134impl From<transaction::SignedTransaction> for SignedTransaction {
135    fn from(stx: transaction::SignedTransaction) -> SignedTransaction {
136        let raw = RawTransaction::from(stx.raw);
137        let tx_hash = Hash::from(stx.tx_hash);
138
139        SignedTransaction {
140            raw:       Some(raw),
141            tx_hash:   Some(tx_hash),
142            pubkey:    stx.pubkey.to_vec(),
143            signature: stx.signature.to_vec(),
144        }
145    }
146}
147
148impl TryFrom<SignedTransaction> for transaction::SignedTransaction {
149    type Error = ProtocolError;
150
151    fn try_from(stx: SignedTransaction) -> Result<transaction::SignedTransaction, Self::Error> {
152        let raw = field!(stx.raw, "SignedTransaction", "raw")?;
153        let tx_hash = field!(stx.tx_hash, "SignedTransaction", "tx_hash")?;
154
155        let stx = transaction::SignedTransaction {
156            raw:       transaction::RawTransaction::try_from(raw)?,
157            tx_hash:   protocol_primitive::Hash::try_from(tx_hash)?,
158            pubkey:    Bytes::from(stx.pubkey),
159            signature: Bytes::from(stx.signature),
160        };
161
162        Ok(stx)
163    }
164}
165
166// #################
167// Codec
168// #################
169
170impl_default_bytes_codec_for!(transaction, [RawTransaction, SignedTransaction]);