solana_sdk/transaction/versioned/
sanitized.rs

1use {
2    super::VersionedTransaction, crate::signature::Signature,
3    solana_program::message::SanitizedVersionedMessage, solana_sanitize::SanitizeError,
4};
5
6/// Wraps a sanitized `VersionedTransaction` to provide a safe API
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct SanitizedVersionedTransaction {
9    /// List of signatures
10    pub(crate) signatures: Vec<Signature>,
11    /// Message to sign.
12    pub(crate) message: SanitizedVersionedMessage,
13}
14
15impl TryFrom<VersionedTransaction> for SanitizedVersionedTransaction {
16    type Error = SanitizeError;
17    fn try_from(tx: VersionedTransaction) -> Result<Self, Self::Error> {
18        Self::try_new(tx)
19    }
20}
21
22impl SanitizedVersionedTransaction {
23    pub fn try_new(tx: VersionedTransaction) -> Result<Self, SanitizeError> {
24        tx.sanitize_signatures()?;
25        Ok(Self {
26            signatures: tx.signatures,
27            message: SanitizedVersionedMessage::try_from(tx.message)?,
28        })
29    }
30
31    pub fn get_message(&self) -> &SanitizedVersionedMessage {
32        &self.message
33    }
34
35    /// Consumes the SanitizedVersionedTransaction, returning the fields individually.
36    pub fn destruct(self) -> (Vec<Signature>, SanitizedVersionedMessage) {
37        (self.signatures, self.message)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use {
44        super::*,
45        solana_program::{
46            hash::Hash,
47            message::{v0, VersionedMessage},
48            pubkey::Pubkey,
49        },
50    };
51
52    #[test]
53    fn test_try_new_with_invalid_signatures() {
54        let tx = VersionedTransaction {
55            signatures: vec![],
56            message: VersionedMessage::V0(
57                v0::Message::try_compile(&Pubkey::new_unique(), &[], &[], Hash::default()).unwrap(),
58            ),
59        };
60
61        assert_eq!(
62            SanitizedVersionedTransaction::try_new(tx),
63            Err(SanitizeError::IndexOutOfBounds)
64        );
65    }
66
67    #[test]
68    fn test_try_new() {
69        let mut message =
70            v0::Message::try_compile(&Pubkey::new_unique(), &[], &[], Hash::default()).unwrap();
71        message.header.num_readonly_signed_accounts += 1;
72
73        let tx = VersionedTransaction {
74            signatures: vec![Signature::default()],
75            message: VersionedMessage::V0(message),
76        };
77
78        assert_eq!(
79            SanitizedVersionedTransaction::try_new(tx),
80            Err(SanitizeError::InvalidValue)
81        );
82    }
83}