solana_block_decoder/transaction/
transaction.rs

1use {
2    crate::{
3        errors::{
4            decode_error::DecodeError,
5        },
6        block::{
7            encoded_block::EncodedTransaction,
8        },
9        message::{
10            message::Message,
11        },
12        decodable::{
13            Decodable,
14        },
15    },
16    serde_derive::{Deserialize, Serialize},
17    solana_short_vec as short_vec,
18    solana_signature::{
19        ParseSignatureError,
20        Signature,
21    },
22    solana_transaction_status_client_types::{
23        TransactionBinaryEncoding,
24    },
25    std::{
26        str::FromStr,
27    },
28    base64::{Engine, prelude::BASE64_STANDARD},
29};
30
31#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)]
32pub struct Transaction {
33    /// A set of signatures of a serialized [`Message`], signed by the first
34    /// keys of the `Message`'s [`account_keys`], where the number of signatures
35    /// is equal to [`num_required_signatures`] of the `Message`'s
36    /// [`MessageHeader`].
37    ///
38    /// [`account_keys`]: Message::account_keys
39    /// [`MessageHeader`]: crate::message::MessageHeader
40    /// [`num_required_signatures`]: crate::message::MessageHeader::num_required_signatures
41    // NOTE: Serialization-related changes must be paired with the direct read at sigverify.
42    #[serde(with = "short_vec")]
43    pub signatures: Vec<Signature>,
44
45    /// The message to sign.
46    pub message: Message,
47}
48
49impl Decodable for Transaction {
50    type Encoded = EncodedTransaction;
51    type Decoded = Transaction;
52
53    fn decode(encoded: &Self::Encoded) -> Result<Self::Decoded, DecodeError> {
54        match encoded {
55            EncodedTransaction::LegacyBinary(s) | EncodedTransaction::Binary(s, TransactionBinaryEncoding::Base58) => {
56                let data = bs58::decode(s)
57                    .into_vec()
58                    .map_err(|_| DecodeError::DeserializeFailed)?;
59                let transaction: Transaction = bincode::deserialize(&data)
60                    .map_err(|_| DecodeError::DeserializeFailed)?;
61                Ok(transaction)
62            }
63            EncodedTransaction::Binary(s, TransactionBinaryEncoding::Base64) => {
64                let data = BASE64_STANDARD.decode(s)
65                    .map_err(|_| DecodeError::DeserializeFailed)?;
66                let transaction: Transaction = bincode::deserialize(&data)
67                    .map_err(|_| DecodeError::DeserializeFailed)?;
68                Ok(transaction)
69            }
70            EncodedTransaction::Json(ui_transaction) => {
71                let message = Message::decode(&ui_transaction.message)?;
72                let signatures: Result<Vec<Signature>, ParseSignatureError> = ui_transaction.signatures.iter()
73                    .map(|s| Signature::from_str(s))
74                    .collect();
75                let signatures = match signatures {
76                    Ok(signatures) => signatures,
77                    Err(error) => return Err(DecodeError::ParseSignatureFailed(error)),
78                };
79                Ok(Transaction {
80                    signatures,
81                    message,
82                })
83            }
84            EncodedTransaction::Accounts(_) => {
85                Err(DecodeError::UnsupportedEncoding)
86            }
87        }
88    }
89}