1use super::transaction::{AlreadyEncoded, EXTRINSIC_FORMAT_VERSION, TransactionSigned};
2use codec::{Compact, Decode, Encode, Error, Input};
3use serde::{Deserialize, Serialize};
4
5#[cfg(not(feature = "generated_metadata"))]
6use crate::avail::{RuntimeCall, RuntimeEvent};
7#[cfg(feature = "generated_metadata")]
8use crate::avail_generated::runtime_types::da_runtime::{RuntimeCall, RuntimeEvent};
9
10#[derive(Clone)]
11pub struct OpaqueTransaction {
12 pub signature: Option<TransactionSigned>,
16 pub call: Vec<u8>,
18}
19
20impl OpaqueTransaction {
21 pub fn pallet_index(&self) -> u8 {
22 self.call[0]
23 }
24
25 pub fn call_index(&self) -> u8 {
26 self.call[1]
27 }
28}
29
30impl TryFrom<Vec<u8>> for OpaqueTransaction {
31 type Error = codec::Error;
32
33 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
34 Self::try_from(value.as_slice())
35 }
36}
37
38impl TryFrom<&Vec<u8>> for OpaqueTransaction {
39 type Error = codec::Error;
40
41 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
42 Self::try_from(value.as_slice())
43 }
44}
45
46impl TryFrom<&[u8]> for OpaqueTransaction {
47 type Error = codec::Error;
48
49 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
50 let mut value = value;
51 Self::decode(&mut value)
52 }
53}
54
55impl Decode for OpaqueTransaction {
56 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
57 let expected_length: Compact<u32> = Decode::decode(input)?;
61 let before_length = input.remaining_len()?;
62
63 let version = input.read_byte()?;
64
65 let is_signed = version & 0b1000_0000 != 0;
66 let version = version & 0b0111_1111;
67 if version != EXTRINSIC_FORMAT_VERSION {
68 return Err("Invalid transaction version".into());
69 }
70
71 let signature = is_signed.then(|| Decode::decode(input)).transpose()?;
72 let call: AlreadyEncoded = Decode::decode(input)?;
73
74 if let Some((before_length, after_length)) = input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a)))
75 {
76 let length = before_length.saturating_sub(after_length);
77
78 if length != expected_length.0 as usize {
79 return Err("Invalid length prefix".into());
80 }
81 }
82
83 Ok(Self {
84 signature,
85 call: call.0,
86 })
87 }
88}
89
90impl Encode for OpaqueTransaction {
91 fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
92 let mut encoded_tx_inner = Vec::new();
93 if let Some(signed) = &self.signature {
94 0x84u8.encode_to(&mut encoded_tx_inner);
95 signed.address.encode_to(&mut encoded_tx_inner);
96 signed.signature.encode_to(&mut encoded_tx_inner);
97 signed.tx_extra.encode_to(&mut encoded_tx_inner);
98 } else {
99 0x4u8.encode_to(&mut encoded_tx_inner);
100 }
101
102 encoded_tx_inner.extend(&self.call);
103 let mut encoded_tx = Compact(encoded_tx_inner.len() as u32).encode();
104 encoded_tx.append(&mut encoded_tx_inner);
105
106 dest.write(&encoded_tx)
107 }
108}
109
110impl Serialize for OpaqueTransaction {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: serde::Serializer,
114 {
115 let bytes = self.encode();
116 impl_serde::serialize::serialize(&bytes, serializer)
117 }
118}
119
120impl<'a> Deserialize<'a> for OpaqueTransaction {
121 fn deserialize<D>(de: D) -> Result<Self, D::Error>
122 where
123 D: serde::Deserializer<'a>,
124 {
125 let r = impl_serde::serialize::deserialize(de)?;
126 Decode::decode(&mut &r[..]).map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
127 }
128}
129
130#[derive(Clone)]
131pub struct DecodedTransaction {
132 pub signature: Option<TransactionSigned>,
136 pub call: RuntimeCall,
138}
139
140impl DecodedTransaction {
141 pub fn app_id(&self) -> Option<u32> {
142 self.signature.as_ref().map(|s| s.tx_extra.app_id)
143 }
144
145 #[cfg(not(feature = "generated_metadata"))]
146 pub fn pallet_index(&self) -> u8 {
147 self.call.pallet_index()
148 }
149
150 #[cfg(not(feature = "generated_metadata"))]
151 pub fn call_index(&self) -> u8 {
152 self.call.call_index()
153 }
154}
155
156impl TryFrom<&Vec<u8>> for DecodedTransaction {
157 type Error = codec::Error;
158
159 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
160 Self::try_from(value.as_slice())
161 }
162}
163
164impl TryFrom<&[u8]> for DecodedTransaction {
165 type Error = codec::Error;
166
167 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
168 let mut value = value;
169 Self::decode(&mut value)
170 }
171}
172
173impl Decode for DecodedTransaction {
174 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
175 let expected_length: Compact<u32> = Decode::decode(input)?;
179 let before_length = input.remaining_len()?;
180
181 let version = input.read_byte()?;
182
183 let is_signed = version & 0b1000_0000 != 0;
184 let version = version & 0b0111_1111;
185 if version != EXTRINSIC_FORMAT_VERSION {
186 return Err("Invalid transaction version".into());
187 }
188
189 let signature = is_signed.then(|| Decode::decode(input)).transpose()?;
190 let call = Decode::decode(input)?;
191
192 if let Some((before_length, after_length)) = input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a)))
193 {
194 let length = before_length.saturating_sub(after_length);
195
196 if length != expected_length.0 as usize {
197 return Err("Invalid length prefix".into());
198 }
199 }
200
201 Ok(Self { signature, call })
202 }
203}
204
205impl Encode for DecodedTransaction {
206 fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
207 let mut encoded_tx_inner = Vec::new();
208 if let Some(signed) = &self.signature {
209 0x84u8.encode_to(&mut encoded_tx_inner);
210 signed.address.encode_to(&mut encoded_tx_inner);
211 signed.signature.encode_to(&mut encoded_tx_inner);
212 signed.tx_extra.encode_to(&mut encoded_tx_inner);
213 } else {
214 0x4u8.encode_to(&mut encoded_tx_inner);
215 }
216
217 self.call.encode_to(&mut encoded_tx_inner);
218 let mut encoded_tx = Compact(encoded_tx_inner.len() as u32).encode();
219 encoded_tx.append(&mut encoded_tx_inner);
220
221 dest.write(&encoded_tx)
222 }
223}
224
225impl Serialize for DecodedTransaction {
226 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
227 where
228 S: serde::Serializer,
229 {
230 let bytes = self.encode();
231 impl_serde::serialize::serialize(&bytes, serializer)
232 }
233}
234
235impl<'a> Deserialize<'a> for DecodedTransaction {
236 fn deserialize<D>(de: D) -> Result<Self, D::Error>
237 where
238 D: serde::Deserializer<'a>,
239 {
240 let r = impl_serde::serialize::deserialize(de)?;
241 Decode::decode(&mut &r[..]).map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
242 }
243}
244
245#[derive(Debug, Clone, Decode)]
246pub struct DecodedEvent {
247 pub phase: RuntimePhase,
248 pub event: RuntimeEvent,
249}
250
251#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Encode, Decode)]
253pub enum RuntimePhase {
254 ApplyExtrinsic(u32),
256 Finalization,
258 Initialization,
260}
261
262#[cfg(test)]
263pub mod test {
264 use std::borrow::Cow;
265
266 use codec::Encode;
267 use subxt_core::utils::{AccountId32, Era};
268
269 use crate::{
270 DecodedTransaction, MultiAddress, MultiSignature, Transaction, TransactionExtra,
271 avail::data_availability::tx::SubmitData, chain_types::TransactionCallLike,
272 decoded_transaction::OpaqueTransaction, transaction::TransactionSigned,
273 };
274
275 #[test]
276 fn test_encoding_decoding() {
277 let call = SubmitData { data: vec![0, 1, 2, 3] }.to_call();
278
279 let account_id = AccountId32([1u8; 32]);
280 let signature = [1u8; 64];
281 let signed = TransactionSigned {
282 address: MultiAddress::Id(account_id),
283 signature: MultiSignature::Sr25519(signature),
284 tx_extra: TransactionExtra {
285 era: Era::Mortal { period: 4, phase: 2 },
286 nonce: 1,
287 tip: 2u128,
288 app_id: 3,
289 },
290 };
291
292 let tx = Transaction {
293 signed: Some(signed.clone()),
294 call: Cow::Owned(call.clone()),
295 };
296
297 let encoded_tx = tx.encode();
298
299 let opaque = OpaqueTransaction::try_from(&encoded_tx).unwrap();
301 let opaque_encoded = opaque.encode();
302
303 assert_eq!(encoded_tx, opaque_encoded);
304
305 let decoded = DecodedTransaction::try_from(&encoded_tx).unwrap();
307 let decoded_encoded = decoded.encode();
308
309 assert_eq!(encoded_tx, decoded_encoded);
310 }
311
312 #[test]
313 fn test_serialize_deserialize() {
314 let call = SubmitData { data: vec![0, 1, 2, 3] }.to_call();
315
316 let account_id = AccountId32([1u8; 32]);
317 let signature = [1u8; 64];
318 let signed = TransactionSigned {
319 address: MultiAddress::Id(account_id),
320 signature: MultiSignature::Sr25519(signature),
321 tx_extra: TransactionExtra {
322 era: Era::Mortal { period: 4, phase: 2 },
323 nonce: 1,
324 tip: 2u128,
325 app_id: 3,
326 },
327 };
328
329 let tx = Transaction {
330 signed: Some(signed.clone()),
331 call: Cow::Owned(call.clone()),
332 };
333
334 let encoded_tx = tx.encode();
335 let expected_serialized = std::format!("0x{}", hex::encode(&encoded_tx));
336
337 let serialized = serde_json::to_string(&tx).unwrap();
339 assert_eq!(serialized.trim_matches('"'), expected_serialized);
340
341 let tx_deserialized: Transaction = serde_json::from_str(&serialized).unwrap();
343 assert_eq!(encoded_tx, tx_deserialized.encode());
344
345 let opaque = OpaqueTransaction::try_from(&encoded_tx).unwrap();
347 let serialized = serde_json::to_string(&opaque).unwrap();
348 assert_eq!(serialized.trim_matches('"'), expected_serialized);
349
350 let opaque_deserialized: OpaqueTransaction = serde_json::from_str(&serialized).unwrap();
352 assert_eq!(encoded_tx, opaque_deserialized.encode());
353
354 let decoded = DecodedTransaction::try_from(&encoded_tx).unwrap();
356 let serialized = serde_json::to_string(&decoded).unwrap();
357 assert_eq!(serialized.trim_matches('"'), expected_serialized);
358
359 let decoded_deserialized: DecodedTransaction = serde_json::from_str(&serialized).unwrap();
361 assert_eq!(encoded_tx, decoded_deserialized.encode());
362 }
363}