solana_sdk/transaction/
mod.rs

1//! Atomically-committed sequences of instructions.
2//!
3//! While [`Instruction`]s are the basic unit of computation in Solana, they are
4//! submitted by clients in [`Transaction`]s containing one or more
5//! instructions, and signed by one or more [`Signer`]s. Solana executes the
6//! instructions in a transaction in order, and only commits any changes if all
7//! instructions terminate without producing an error or exception.
8//!
9//! Transactions do not directly contain their instructions but instead include
10//! a [`Message`], a precompiled representation of a sequence of instructions.
11//! `Message`'s constructors handle the complex task of reordering the
12//! individual lists of accounts required by each instruction into a single flat
13//! list of deduplicated accounts required by the Solana runtime. The
14//! `Transaction` type has constructors that build the `Message` so that clients
15//! don't need to interact with them directly.
16//!
17//! Prior to submission to the network, transactions must be signed by one or or
18//! more keypairs, and this signing is typically performed by an abstract
19//! [`Signer`], which may be a [`Keypair`] but may also be other types of
20//! signers including remote wallets, such as Ledger devices, as represented by
21//! the [`RemoteKeypair`] type in the [`solana-remote-wallet`] crate.
22//!
23//! [`Signer`]: crate::signer::Signer
24//! [`Keypair`]: crate::signer::keypair::Keypair
25//! [`solana-remote-wallet`]: https://docs.rs/solana-remote-wallet/latest/
26//! [`RemoteKeypair`]: https://docs.rs/solana-remote-wallet/latest/solana_remote_wallet/remote_keypair/struct.RemoteKeypair.html
27//!
28//! Every transaction must be signed by a fee-paying account, the account from
29//! which the cost of executing the transaction is withdrawn. Other required
30//! signatures are determined by the requirements of the programs being executed
31//! by each instruction, and are conventionally specified by that program's
32//! documentation.
33//!
34//! When signing a transaction, a recent blockhash must be provided (which can
35//! be retrieved with [`RpcClient::get_latest_blockhash`]). This allows
36//! validators to drop old but unexecuted transactions; and to distinguish
37//! between accidentally duplicated transactions and intentionally duplicated
38//! transactions — any identical transactions will not be executed more
39//! than once, so updating the blockhash between submitting otherwise identical
40//! transactions makes them unique. If a client must sign a transaction long
41//! before submitting it to the network, then it can use the _[durable
42//! transaction nonce]_ mechanism instead of a recent blockhash to ensure unique
43//! transactions.
44//!
45//! [`RpcClient::get_latest_blockhash`]: https://docs.rs/solana-rpc-client/latest/solana_rpc_client/rpc_client/struct.RpcClient.html#method.get_latest_blockhash
46//! [durable transaction nonce]: https://docs.solanalabs.com/implemented-proposals/durable-tx-nonces
47//!
48//! # Examples
49//!
50//! This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
51//!
52//! [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
53//! [`anyhow`]: https://docs.rs/anyhow
54//!
55//! ```
56//! # use solana_sdk::example_mocks::solana_rpc_client;
57//! use anyhow::Result;
58//! use borsh::{BorshSerialize, BorshDeserialize};
59//! use solana_rpc_client::rpc_client::RpcClient;
60//! use solana_sdk::{
61//!      instruction::Instruction,
62//!      message::Message,
63//!      pubkey::Pubkey,
64//!      signature::{Keypair, Signer},
65//!      transaction::Transaction,
66//! };
67//!
68//! // A custom program instruction. This would typically be defined in
69//! // another crate so it can be shared between the on-chain program and
70//! // the client.
71//! #[derive(BorshSerialize, BorshDeserialize)]
72//! enum BankInstruction {
73//!     Initialize,
74//!     Deposit { lamports: u64 },
75//!     Withdraw { lamports: u64 },
76//! }
77//!
78//! fn send_initialize_tx(
79//!     client: &RpcClient,
80//!     program_id: Pubkey,
81//!     payer: &Keypair
82//! ) -> Result<()> {
83//!
84//!     let bank_instruction = BankInstruction::Initialize;
85//!
86//!     let instruction = Instruction::new_with_borsh(
87//!         program_id,
88//!         &bank_instruction,
89//!         vec![],
90//!     );
91//!
92//!     let blockhash = client.get_latest_blockhash()?;
93//!     let mut tx = Transaction::new_signed_with_payer(
94//!         &[instruction],
95//!         Some(&payer.pubkey()),
96//!         &[payer],
97//!         blockhash,
98//!     );
99//!     client.send_and_confirm_transaction(&tx)?;
100//!
101//!     Ok(())
102//! }
103//! #
104//! # let client = RpcClient::new(String::new());
105//! # let program_id = Pubkey::new_unique();
106//! # let payer = Keypair::new();
107//! # send_initialize_tx(&client, program_id, &payer)?;
108//! #
109//! # Ok::<(), anyhow::Error>(())
110//! ```
111
112#![cfg(feature = "full")]
113
114#[cfg(target_arch = "wasm32")]
115use crate::wasm_bindgen;
116use {
117    crate::{
118        hash::Hash,
119        instruction::{CompiledInstruction, Instruction},
120        message::Message,
121        nonce::NONCED_TX_MARKER_IX_INDEX,
122        precompiles::verify_if_precompile,
123        program_utils::limited_deserialize,
124        pubkey::Pubkey,
125        signature::{Signature, SignerError},
126        signers::Signers,
127    },
128    serde::Serialize,
129    solana_feature_set as feature_set,
130    solana_program::{system_instruction::SystemInstruction, system_program},
131    solana_sanitize::{Sanitize, SanitizeError},
132    solana_short_vec as short_vec,
133    std::result,
134};
135
136mod sanitized;
137mod versioned;
138
139#[deprecated(since = "2.1.0", note = "Use solana_transaction_error crate instead")]
140pub use solana_transaction_error::*;
141pub use {sanitized::*, versioned::*};
142
143#[derive(PartialEq, Eq, Clone, Copy, Debug)]
144pub enum TransactionVerificationMode {
145    HashOnly,
146    HashAndVerifyPrecompiles,
147    FullVerification,
148}
149
150pub type Result<T> = result::Result<T, TransactionError>;
151
152/// An atomically-committed sequence of instructions.
153///
154/// While [`Instruction`]s are the basic unit of computation in Solana,
155/// they are submitted by clients in [`Transaction`]s containing one or
156/// more instructions, and signed by one or more [`Signer`]s.
157///
158/// [`Signer`]: crate::signer::Signer
159///
160/// See the [module documentation] for more details about transactions.
161///
162/// [module documentation]: self
163///
164/// Some constructors accept an optional `payer`, the account responsible for
165/// paying the cost of executing a transaction. In most cases, callers should
166/// specify the payer explicitly in these constructors. In some cases though,
167/// the caller is not _required_ to specify the payer, but is still allowed to:
168/// in the [`Message`] structure, the first account is always the fee-payer, so
169/// if the caller has knowledge that the first account of the constructed
170/// transaction's `Message` is both a signer and the expected fee-payer, then
171/// redundantly specifying the fee-payer is not strictly required.
172#[cfg(not(target_arch = "wasm32"))]
173#[cfg_attr(
174    feature = "frozen-abi",
175    derive(AbiExample),
176    frozen_abi(digest = "686AAhRhjXpqKidmJEdHHcJCL9XxCxebu8Xmku9shp83")
177)]
178#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)]
179pub struct Transaction {
180    /// A set of signatures of a serialized [`Message`], signed by the first
181    /// keys of the `Message`'s [`account_keys`], where the number of signatures
182    /// is equal to [`num_required_signatures`] of the `Message`'s
183    /// [`MessageHeader`].
184    ///
185    /// [`account_keys`]: Message::account_keys
186    /// [`MessageHeader`]: crate::message::MessageHeader
187    /// [`num_required_signatures`]: crate::message::MessageHeader::num_required_signatures
188    // NOTE: Serialization-related changes must be paired with the direct read at sigverify.
189    #[serde(with = "short_vec")]
190    pub signatures: Vec<Signature>,
191
192    /// The message to sign.
193    pub message: Message,
194}
195
196/// wasm-bindgen version of the Transaction struct.
197/// This duplication is required until https://github.com/rustwasm/wasm-bindgen/issues/3671
198/// is fixed. This must not diverge from the regular non-wasm Transaction struct.
199#[cfg(target_arch = "wasm32")]
200#[wasm_bindgen]
201#[cfg_attr(
202    feature = "frozen-abi",
203    derive(AbiExample),
204    frozen_abi(digest = "H7xQFcd1MtMv9QKZWGatBAXwhg28tpeX59P3s8ZZLAY4")
205)]
206#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)]
207pub struct Transaction {
208    #[wasm_bindgen(skip)]
209    #[serde(with = "short_vec")]
210    pub signatures: Vec<Signature>,
211
212    #[wasm_bindgen(skip)]
213    pub message: Message,
214}
215
216impl Sanitize for Transaction {
217    fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
218        if self.message.header.num_required_signatures as usize > self.signatures.len() {
219            return Err(SanitizeError::IndexOutOfBounds);
220        }
221        if self.signatures.len() > self.message.account_keys.len() {
222            return Err(SanitizeError::IndexOutOfBounds);
223        }
224        self.message.sanitize()
225    }
226}
227
228impl Transaction {
229    /// Create an unsigned transaction from a [`Message`].
230    ///
231    /// # Examples
232    ///
233    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
234    ///
235    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
236    /// [`anyhow`]: https://docs.rs/anyhow
237    ///
238    /// ```
239    /// # use solana_sdk::example_mocks::solana_rpc_client;
240    /// use anyhow::Result;
241    /// use borsh::{BorshSerialize, BorshDeserialize};
242    /// use solana_rpc_client::rpc_client::RpcClient;
243    /// use solana_sdk::{
244    ///      instruction::Instruction,
245    ///      message::Message,
246    ///      pubkey::Pubkey,
247    ///      signature::{Keypair, Signer},
248    ///      transaction::Transaction,
249    /// };
250    ///
251    /// // A custom program instruction. This would typically be defined in
252    /// // another crate so it can be shared between the on-chain program and
253    /// // the client.
254    /// #[derive(BorshSerialize, BorshDeserialize)]
255    /// enum BankInstruction {
256    ///     Initialize,
257    ///     Deposit { lamports: u64 },
258    ///     Withdraw { lamports: u64 },
259    /// }
260    ///
261    /// fn send_initialize_tx(
262    ///     client: &RpcClient,
263    ///     program_id: Pubkey,
264    ///     payer: &Keypair
265    /// ) -> Result<()> {
266    ///
267    ///     let bank_instruction = BankInstruction::Initialize;
268    ///
269    ///     let instruction = Instruction::new_with_borsh(
270    ///         program_id,
271    ///         &bank_instruction,
272    ///         vec![],
273    ///     );
274    ///
275    ///     let message = Message::new(
276    ///         &[instruction],
277    ///         Some(&payer.pubkey()),
278    ///     );
279    ///
280    ///     let mut tx = Transaction::new_unsigned(message);
281    ///     let blockhash = client.get_latest_blockhash()?;
282    ///     tx.sign(&[payer], blockhash);
283    ///     client.send_and_confirm_transaction(&tx)?;
284    ///
285    ///     Ok(())
286    /// }
287    /// #
288    /// # let client = RpcClient::new(String::new());
289    /// # let program_id = Pubkey::new_unique();
290    /// # let payer = Keypair::new();
291    /// # send_initialize_tx(&client, program_id, &payer)?;
292    /// #
293    /// # Ok::<(), anyhow::Error>(())
294    /// ```
295    pub fn new_unsigned(message: Message) -> Self {
296        Self {
297            signatures: vec![Signature::default(); message.header.num_required_signatures as usize],
298            message,
299        }
300    }
301
302    /// Create a fully-signed transaction from a [`Message`].
303    ///
304    /// # Panics
305    ///
306    /// Panics when signing fails. See [`Transaction::try_sign`] and
307    /// [`Transaction::try_partial_sign`] for a full description of failure
308    /// scenarios.
309    ///
310    /// # Examples
311    ///
312    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
313    ///
314    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
315    /// [`anyhow`]: https://docs.rs/anyhow
316    ///
317    /// ```
318    /// # use solana_sdk::example_mocks::solana_rpc_client;
319    /// use anyhow::Result;
320    /// use borsh::{BorshSerialize, BorshDeserialize};
321    /// use solana_rpc_client::rpc_client::RpcClient;
322    /// use solana_sdk::{
323    ///      instruction::Instruction,
324    ///      message::Message,
325    ///      pubkey::Pubkey,
326    ///      signature::{Keypair, Signer},
327    ///      transaction::Transaction,
328    /// };
329    ///
330    /// // A custom program instruction. This would typically be defined in
331    /// // another crate so it can be shared between the on-chain program and
332    /// // the client.
333    /// #[derive(BorshSerialize, BorshDeserialize)]
334    /// enum BankInstruction {
335    ///     Initialize,
336    ///     Deposit { lamports: u64 },
337    ///     Withdraw { lamports: u64 },
338    /// }
339    ///
340    /// fn send_initialize_tx(
341    ///     client: &RpcClient,
342    ///     program_id: Pubkey,
343    ///     payer: &Keypair
344    /// ) -> Result<()> {
345    ///
346    ///     let bank_instruction = BankInstruction::Initialize;
347    ///
348    ///     let instruction = Instruction::new_with_borsh(
349    ///         program_id,
350    ///         &bank_instruction,
351    ///         vec![],
352    ///     );
353    ///
354    ///     let message = Message::new(
355    ///         &[instruction],
356    ///         Some(&payer.pubkey()),
357    ///     );
358    ///
359    ///     let blockhash = client.get_latest_blockhash()?;
360    ///     let mut tx = Transaction::new(&[payer], message, blockhash);
361    ///     client.send_and_confirm_transaction(&tx)?;
362    ///
363    ///     Ok(())
364    /// }
365    /// #
366    /// # let client = RpcClient::new(String::new());
367    /// # let program_id = Pubkey::new_unique();
368    /// # let payer = Keypair::new();
369    /// # send_initialize_tx(&client, program_id, &payer)?;
370    /// #
371    /// # Ok::<(), anyhow::Error>(())
372    /// ```
373    pub fn new<T: Signers + ?Sized>(
374        from_keypairs: &T,
375        message: Message,
376        recent_blockhash: Hash,
377    ) -> Transaction {
378        let mut tx = Self::new_unsigned(message);
379        tx.sign(from_keypairs, recent_blockhash);
380        tx
381    }
382
383    /// Create an unsigned transaction from a list of [`Instruction`]s.
384    ///
385    /// `payer` is the account responsible for paying the cost of executing the
386    /// transaction. It is typically provided, but is optional in some cases.
387    /// See the [`Transaction`] docs for more.
388    ///
389    /// # Examples
390    ///
391    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
392    ///
393    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
394    /// [`anyhow`]: https://docs.rs/anyhow
395    ///
396    /// ```
397    /// # use solana_sdk::example_mocks::solana_rpc_client;
398    /// use anyhow::Result;
399    /// use borsh::{BorshSerialize, BorshDeserialize};
400    /// use solana_rpc_client::rpc_client::RpcClient;
401    /// use solana_sdk::{
402    ///      instruction::Instruction,
403    ///      message::Message,
404    ///      pubkey::Pubkey,
405    ///      signature::{Keypair, Signer},
406    ///      transaction::Transaction,
407    /// };
408    ///
409    /// // A custom program instruction. This would typically be defined in
410    /// // another crate so it can be shared between the on-chain program and
411    /// // the client.
412    /// #[derive(BorshSerialize, BorshDeserialize)]
413    /// enum BankInstruction {
414    ///     Initialize,
415    ///     Deposit { lamports: u64 },
416    ///     Withdraw { lamports: u64 },
417    /// }
418    ///
419    /// fn send_initialize_tx(
420    ///     client: &RpcClient,
421    ///     program_id: Pubkey,
422    ///     payer: &Keypair
423    /// ) -> Result<()> {
424    ///
425    ///     let bank_instruction = BankInstruction::Initialize;
426    ///
427    ///     let instruction = Instruction::new_with_borsh(
428    ///         program_id,
429    ///         &bank_instruction,
430    ///         vec![],
431    ///     );
432    ///
433    ///     let mut tx = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
434    ///     let blockhash = client.get_latest_blockhash()?;
435    ///     tx.sign(&[payer], blockhash);
436    ///     client.send_and_confirm_transaction(&tx)?;
437    ///
438    ///     Ok(())
439    /// }
440    /// #
441    /// # let client = RpcClient::new(String::new());
442    /// # let program_id = Pubkey::new_unique();
443    /// # let payer = Keypair::new();
444    /// # send_initialize_tx(&client, program_id, &payer)?;
445    /// #
446    /// # Ok::<(), anyhow::Error>(())
447    /// ```
448    pub fn new_with_payer(instructions: &[Instruction], payer: Option<&Pubkey>) -> Self {
449        let message = Message::new(instructions, payer);
450        Self::new_unsigned(message)
451    }
452
453    /// Create a fully-signed transaction from a list of [`Instruction`]s.
454    ///
455    /// `payer` is the account responsible for paying the cost of executing the
456    /// transaction. It is typically provided, but is optional in some cases.
457    /// See the [`Transaction`] docs for more.
458    ///
459    /// # Panics
460    ///
461    /// Panics when signing fails. See [`Transaction::try_sign`] and
462    /// [`Transaction::try_partial_sign`] for a full description of failure
463    /// scenarios.
464    ///
465    /// # Examples
466    ///
467    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
468    ///
469    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
470    /// [`anyhow`]: https://docs.rs/anyhow
471    ///
472    /// ```
473    /// # use solana_sdk::example_mocks::solana_rpc_client;
474    /// use anyhow::Result;
475    /// use borsh::{BorshSerialize, BorshDeserialize};
476    /// use solana_rpc_client::rpc_client::RpcClient;
477    /// use solana_sdk::{
478    ///      instruction::Instruction,
479    ///      message::Message,
480    ///      pubkey::Pubkey,
481    ///      signature::{Keypair, Signer},
482    ///      transaction::Transaction,
483    /// };
484    ///
485    /// // A custom program instruction. This would typically be defined in
486    /// // another crate so it can be shared between the on-chain program and
487    /// // the client.
488    /// #[derive(BorshSerialize, BorshDeserialize)]
489    /// enum BankInstruction {
490    ///     Initialize,
491    ///     Deposit { lamports: u64 },
492    ///     Withdraw { lamports: u64 },
493    /// }
494    ///
495    /// fn send_initialize_tx(
496    ///     client: &RpcClient,
497    ///     program_id: Pubkey,
498    ///     payer: &Keypair
499    /// ) -> Result<()> {
500    ///
501    ///     let bank_instruction = BankInstruction::Initialize;
502    ///
503    ///     let instruction = Instruction::new_with_borsh(
504    ///         program_id,
505    ///         &bank_instruction,
506    ///         vec![],
507    ///     );
508    ///
509    ///     let blockhash = client.get_latest_blockhash()?;
510    ///     let mut tx = Transaction::new_signed_with_payer(
511    ///         &[instruction],
512    ///         Some(&payer.pubkey()),
513    ///         &[payer],
514    ///         blockhash,
515    ///     );
516    ///     client.send_and_confirm_transaction(&tx)?;
517    ///
518    ///     Ok(())
519    /// }
520    /// #
521    /// # let client = RpcClient::new(String::new());
522    /// # let program_id = Pubkey::new_unique();
523    /// # let payer = Keypair::new();
524    /// # send_initialize_tx(&client, program_id, &payer)?;
525    /// #
526    /// # Ok::<(), anyhow::Error>(())
527    /// ```
528    pub fn new_signed_with_payer<T: Signers + ?Sized>(
529        instructions: &[Instruction],
530        payer: Option<&Pubkey>,
531        signing_keypairs: &T,
532        recent_blockhash: Hash,
533    ) -> Self {
534        let message = Message::new(instructions, payer);
535        Self::new(signing_keypairs, message, recent_blockhash)
536    }
537
538    /// Create a fully-signed transaction from pre-compiled instructions.
539    ///
540    /// # Arguments
541    ///
542    /// * `from_keypairs` - The keys used to sign the transaction.
543    /// * `keys` - The keys for the transaction.  These are the program state
544    ///    instances or lamport recipient keys.
545    /// * `recent_blockhash` - The PoH hash.
546    /// * `program_ids` - The keys that identify programs used in the `instruction` vector.
547    /// * `instructions` - Instructions that will be executed atomically.
548    ///
549    /// # Panics
550    ///
551    /// Panics when signing fails. See [`Transaction::try_sign`] and for a full
552    /// description of failure conditions.
553    pub fn new_with_compiled_instructions<T: Signers + ?Sized>(
554        from_keypairs: &T,
555        keys: &[Pubkey],
556        recent_blockhash: Hash,
557        program_ids: Vec<Pubkey>,
558        instructions: Vec<CompiledInstruction>,
559    ) -> Self {
560        let mut account_keys = from_keypairs.pubkeys();
561        let from_keypairs_len = account_keys.len();
562        account_keys.extend_from_slice(keys);
563        account_keys.extend(&program_ids);
564        let message = Message::new_with_compiled_instructions(
565            from_keypairs_len as u8,
566            0,
567            program_ids.len() as u8,
568            account_keys,
569            Hash::default(),
570            instructions,
571        );
572        Transaction::new(from_keypairs, message, recent_blockhash)
573    }
574
575    /// Get the data for an instruction at the given index.
576    ///
577    /// The `instruction_index` corresponds to the [`instructions`] vector of
578    /// the `Transaction`'s [`Message`] value.
579    ///
580    /// [`instructions`]: Message::instructions
581    ///
582    /// # Panics
583    ///
584    /// Panics if `instruction_index` is greater than or equal to the number of
585    /// instructions in the transaction.
586    pub fn data(&self, instruction_index: usize) -> &[u8] {
587        &self.message.instructions[instruction_index].data
588    }
589
590    fn key_index(&self, instruction_index: usize, accounts_index: usize) -> Option<usize> {
591        self.message
592            .instructions
593            .get(instruction_index)
594            .and_then(|instruction| instruction.accounts.get(accounts_index))
595            .map(|&account_keys_index| account_keys_index as usize)
596    }
597
598    /// Get the `Pubkey` of an account required by one of the instructions in
599    /// the transaction.
600    ///
601    /// The `instruction_index` corresponds to the [`instructions`] vector of
602    /// the `Transaction`'s [`Message`] value; and the `account_index` to the
603    /// [`accounts`] vector of the message's [`CompiledInstruction`]s.
604    ///
605    /// [`instructions`]: Message::instructions
606    /// [`accounts`]: CompiledInstruction::accounts
607    /// [`CompiledInstruction`]: CompiledInstruction
608    ///
609    /// Returns `None` if `instruction_index` is greater than or equal to the
610    /// number of instructions in the transaction; or if `accounts_index` is
611    /// greater than or equal to the number of accounts in the instruction.
612    pub fn key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
613        self.key_index(instruction_index, accounts_index)
614            .and_then(|account_keys_index| self.message.account_keys.get(account_keys_index))
615    }
616
617    /// Get the `Pubkey` of a signing account required by one of the
618    /// instructions in the transaction.
619    ///
620    /// The transaction does not need to be signed for this function to return a
621    /// signing account's pubkey.
622    ///
623    /// Returns `None` if the indexed account is not required to sign the
624    /// transaction. Returns `None` if the [`signatures`] field does not contain
625    /// enough elements to hold a signature for the indexed account (this should
626    /// only be possible if `Transaction` has been manually constructed).
627    ///
628    /// [`signatures`]: Transaction::signatures
629    ///
630    /// Returns `None` if `instruction_index` is greater than or equal to the
631    /// number of instructions in the transaction; or if `accounts_index` is
632    /// greater than or equal to the number of accounts in the instruction.
633    pub fn signer_key(&self, instruction_index: usize, accounts_index: usize) -> Option<&Pubkey> {
634        match self.key_index(instruction_index, accounts_index) {
635            None => None,
636            Some(signature_index) => {
637                if signature_index >= self.signatures.len() {
638                    return None;
639                }
640                self.message.account_keys.get(signature_index)
641            }
642        }
643    }
644
645    /// Return the message containing all data that should be signed.
646    pub fn message(&self) -> &Message {
647        &self.message
648    }
649
650    /// Return the serialized message data to sign.
651    pub fn message_data(&self) -> Vec<u8> {
652        self.message().serialize()
653    }
654
655    /// Sign the transaction.
656    ///
657    /// This method fully signs a transaction with all required signers, which
658    /// must be present in the `keypairs` slice. To sign with only some of the
659    /// required signers, use [`Transaction::partial_sign`].
660    ///
661    /// If `recent_blockhash` is different than recorded in the transaction message's
662    /// [`recent_blockhash`] field, then the message's `recent_blockhash` will be updated
663    /// to the provided `recent_blockhash`, and any prior signatures will be cleared.
664    ///
665    /// [`recent_blockhash`]: Message::recent_blockhash
666    ///
667    /// # Panics
668    ///
669    /// Panics when signing fails. Use [`Transaction::try_sign`] to handle the
670    /// error. See the documentation for [`Transaction::try_sign`] for a full description of
671    /// failure conditions.
672    ///
673    /// # Examples
674    ///
675    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
676    ///
677    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
678    /// [`anyhow`]: https://docs.rs/anyhow
679    ///
680    /// ```
681    /// # use solana_sdk::example_mocks::solana_rpc_client;
682    /// use anyhow::Result;
683    /// use borsh::{BorshSerialize, BorshDeserialize};
684    /// use solana_rpc_client::rpc_client::RpcClient;
685    /// use solana_sdk::{
686    ///      instruction::Instruction,
687    ///      message::Message,
688    ///      pubkey::Pubkey,
689    ///      signature::{Keypair, Signer},
690    ///      transaction::Transaction,
691    /// };
692    ///
693    /// // A custom program instruction. This would typically be defined in
694    /// // another crate so it can be shared between the on-chain program and
695    /// // the client.
696    /// #[derive(BorshSerialize, BorshDeserialize)]
697    /// enum BankInstruction {
698    ///     Initialize,
699    ///     Deposit { lamports: u64 },
700    ///     Withdraw { lamports: u64 },
701    /// }
702    ///
703    /// fn send_initialize_tx(
704    ///     client: &RpcClient,
705    ///     program_id: Pubkey,
706    ///     payer: &Keypair
707    /// ) -> Result<()> {
708    ///
709    ///     let bank_instruction = BankInstruction::Initialize;
710    ///
711    ///     let instruction = Instruction::new_with_borsh(
712    ///         program_id,
713    ///         &bank_instruction,
714    ///         vec![],
715    ///     );
716    ///
717    ///     let mut tx = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
718    ///     let blockhash = client.get_latest_blockhash()?;
719    ///     tx.sign(&[payer], blockhash);
720    ///     client.send_and_confirm_transaction(&tx)?;
721    ///
722    ///     Ok(())
723    /// }
724    /// #
725    /// # let client = RpcClient::new(String::new());
726    /// # let program_id = Pubkey::new_unique();
727    /// # let payer = Keypair::new();
728    /// # send_initialize_tx(&client, program_id, &payer)?;
729    /// #
730    /// # Ok::<(), anyhow::Error>(())
731    /// ```
732    pub fn sign<T: Signers + ?Sized>(&mut self, keypairs: &T, recent_blockhash: Hash) {
733        if let Err(e) = self.try_sign(keypairs, recent_blockhash) {
734            panic!("Transaction::sign failed with error {e:?}");
735        }
736    }
737
738    /// Sign the transaction with a subset of required keys.
739    ///
740    /// Unlike [`Transaction::sign`], this method does not require all keypairs
741    /// to be provided, allowing a transaction to be signed in multiple steps.
742    ///
743    /// It is permitted to sign a transaction with the same keypair multiple
744    /// times.
745    ///
746    /// If `recent_blockhash` is different than recorded in the transaction message's
747    /// [`recent_blockhash`] field, then the message's `recent_blockhash` will be updated
748    /// to the provided `recent_blockhash`, and any prior signatures will be cleared.
749    ///
750    /// [`recent_blockhash`]: Message::recent_blockhash
751    ///
752    /// # Panics
753    ///
754    /// Panics when signing fails. Use [`Transaction::try_partial_sign`] to
755    /// handle the error. See the documentation for
756    /// [`Transaction::try_partial_sign`] for a full description of failure
757    /// conditions.
758    pub fn partial_sign<T: Signers + ?Sized>(&mut self, keypairs: &T, recent_blockhash: Hash) {
759        if let Err(e) = self.try_partial_sign(keypairs, recent_blockhash) {
760            panic!("Transaction::partial_sign failed with error {e:?}");
761        }
762    }
763
764    /// Sign the transaction with a subset of required keys.
765    ///
766    /// This places each of the signatures created from `keypairs` in the
767    /// corresponding position, as specified in the `positions` vector, in the
768    /// transactions [`signatures`] field. It does not verify that the signature
769    /// positions are correct.
770    ///
771    /// [`signatures`]: Transaction::signatures
772    ///
773    /// # Panics
774    ///
775    /// Panics if signing fails. Use [`Transaction::try_partial_sign_unchecked`]
776    /// to handle the error.
777    pub fn partial_sign_unchecked<T: Signers + ?Sized>(
778        &mut self,
779        keypairs: &T,
780        positions: Vec<usize>,
781        recent_blockhash: Hash,
782    ) {
783        if let Err(e) = self.try_partial_sign_unchecked(keypairs, positions, recent_blockhash) {
784            panic!("Transaction::partial_sign_unchecked failed with error {e:?}");
785        }
786    }
787
788    /// Sign the transaction, returning any errors.
789    ///
790    /// This method fully signs a transaction with all required signers, which
791    /// must be present in the `keypairs` slice. To sign with only some of the
792    /// required signers, use [`Transaction::try_partial_sign`].
793    ///
794    /// If `recent_blockhash` is different than recorded in the transaction message's
795    /// [`recent_blockhash`] field, then the message's `recent_blockhash` will be updated
796    /// to the provided `recent_blockhash`, and any prior signatures will be cleared.
797    ///
798    /// [`recent_blockhash`]: Message::recent_blockhash
799    ///
800    /// # Errors
801    ///
802    /// Signing will fail if some required signers are not provided in
803    /// `keypairs`; or, if the transaction has previously been partially signed,
804    /// some of the remaining required signers are not provided in `keypairs`.
805    /// In other words, the transaction must be fully signed as a result of
806    /// calling this function. The error is [`SignerError::NotEnoughSigners`].
807    ///
808    /// Signing will fail for any of the reasons described in the documentation
809    /// for [`Transaction::try_partial_sign`].
810    ///
811    /// # Examples
812    ///
813    /// This example uses the [`solana_rpc_client`] and [`anyhow`] crates.
814    ///
815    /// [`solana_rpc_client`]: https://docs.rs/solana-rpc-client
816    /// [`anyhow`]: https://docs.rs/anyhow
817    ///
818    /// ```
819    /// # use solana_sdk::example_mocks::solana_rpc_client;
820    /// use anyhow::Result;
821    /// use borsh::{BorshSerialize, BorshDeserialize};
822    /// use solana_rpc_client::rpc_client::RpcClient;
823    /// use solana_sdk::{
824    ///      instruction::Instruction,
825    ///      message::Message,
826    ///      pubkey::Pubkey,
827    ///      signature::{Keypair, Signer},
828    ///      transaction::Transaction,
829    /// };
830    ///
831    /// // A custom program instruction. This would typically be defined in
832    /// // another crate so it can be shared between the on-chain program and
833    /// // the client.
834    /// #[derive(BorshSerialize, BorshDeserialize)]
835    /// enum BankInstruction {
836    ///     Initialize,
837    ///     Deposit { lamports: u64 },
838    ///     Withdraw { lamports: u64 },
839    /// }
840    ///
841    /// fn send_initialize_tx(
842    ///     client: &RpcClient,
843    ///     program_id: Pubkey,
844    ///     payer: &Keypair
845    /// ) -> Result<()> {
846    ///
847    ///     let bank_instruction = BankInstruction::Initialize;
848    ///
849    ///     let instruction = Instruction::new_with_borsh(
850    ///         program_id,
851    ///         &bank_instruction,
852    ///         vec![],
853    ///     );
854    ///
855    ///     let mut tx = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
856    ///     let blockhash = client.get_latest_blockhash()?;
857    ///     tx.try_sign(&[payer], blockhash)?;
858    ///     client.send_and_confirm_transaction(&tx)?;
859    ///
860    ///     Ok(())
861    /// }
862    /// #
863    /// # let client = RpcClient::new(String::new());
864    /// # let program_id = Pubkey::new_unique();
865    /// # let payer = Keypair::new();
866    /// # send_initialize_tx(&client, program_id, &payer)?;
867    /// #
868    /// # Ok::<(), anyhow::Error>(())
869    /// ```
870    pub fn try_sign<T: Signers + ?Sized>(
871        &mut self,
872        keypairs: &T,
873        recent_blockhash: Hash,
874    ) -> result::Result<(), SignerError> {
875        self.try_partial_sign(keypairs, recent_blockhash)?;
876
877        if !self.is_signed() {
878            Err(SignerError::NotEnoughSigners)
879        } else {
880            Ok(())
881        }
882    }
883
884    /// Sign the transaction with a subset of required keys, returning any errors.
885    ///
886    /// Unlike [`Transaction::try_sign`], this method does not require all
887    /// keypairs to be provided, allowing a transaction to be signed in multiple
888    /// steps.
889    ///
890    /// It is permitted to sign a transaction with the same keypair multiple
891    /// times.
892    ///
893    /// If `recent_blockhash` is different than recorded in the transaction message's
894    /// [`recent_blockhash`] field, then the message's `recent_blockhash` will be updated
895    /// to the provided `recent_blockhash`, and any prior signatures will be cleared.
896    ///
897    /// [`recent_blockhash`]: Message::recent_blockhash
898    ///
899    /// # Errors
900    ///
901    /// Signing will fail if
902    ///
903    /// - The transaction's [`Message`] is malformed such that the number of
904    ///   required signatures recorded in its header
905    ///   ([`num_required_signatures`]) is greater than the length of its
906    ///   account keys ([`account_keys`]). The error is
907    ///   [`SignerError::TransactionError`] where the interior
908    ///   [`TransactionError`] is [`TransactionError::InvalidAccountIndex`].
909    /// - Any of the provided signers in `keypairs` is not a required signer of
910    ///   the message. The error is [`SignerError::KeypairPubkeyMismatch`].
911    /// - Any of the signers is a [`Presigner`], and its provided signature is
912    ///   incorrect. The error is [`SignerError::PresignerError`] where the
913    ///   interior [`PresignerError`] is
914    ///   [`PresignerError::VerificationFailure`].
915    /// - The signer is a [`RemoteKeypair`] and
916    ///   - It does not understand the input provided ([`SignerError::InvalidInput`]).
917    ///   - The device cannot be found ([`SignerError::NoDeviceFound`]).
918    ///   - The user cancels the signing ([`SignerError::UserCancel`]).
919    ///   - An error was encountered connecting ([`SignerError::Connection`]).
920    ///   - Some device-specific protocol error occurs ([`SignerError::Protocol`]).
921    ///   - Some other error occurs ([`SignerError::Custom`]).
922    ///
923    /// See the documentation for the [`solana-remote-wallet`] crate for details
924    /// on the operation of [`RemoteKeypair`] signers.
925    ///
926    /// [`num_required_signatures`]: crate::message::MessageHeader::num_required_signatures
927    /// [`account_keys`]: Message::account_keys
928    /// [`Presigner`]: crate::signer::presigner::Presigner
929    /// [`PresignerError`]: crate::signer::presigner::PresignerError
930    /// [`PresignerError::VerificationFailure`]: crate::signer::presigner::PresignerError::VerificationFailure
931    /// [`solana-remote-wallet`]: https://docs.rs/solana-remote-wallet/latest/
932    /// [`RemoteKeypair`]: https://docs.rs/solana-remote-wallet/latest/solana_remote_wallet/remote_keypair/struct.RemoteKeypair.html
933    pub fn try_partial_sign<T: Signers + ?Sized>(
934        &mut self,
935        keypairs: &T,
936        recent_blockhash: Hash,
937    ) -> result::Result<(), SignerError> {
938        let positions = self.get_signing_keypair_positions(&keypairs.pubkeys())?;
939        if positions.iter().any(|pos| pos.is_none()) {
940            return Err(SignerError::KeypairPubkeyMismatch);
941        }
942        let positions: Vec<usize> = positions.iter().map(|pos| pos.unwrap()).collect();
943        self.try_partial_sign_unchecked(keypairs, positions, recent_blockhash)
944    }
945
946    /// Sign the transaction with a subset of required keys, returning any
947    /// errors.
948    ///
949    /// This places each of the signatures created from `keypairs` in the
950    /// corresponding position, as specified in the `positions` vector, in the
951    /// transactions [`signatures`] field. It does not verify that the signature
952    /// positions are correct.
953    ///
954    /// [`signatures`]: Transaction::signatures
955    ///
956    /// # Errors
957    ///
958    /// Returns an error if signing fails.
959    pub fn try_partial_sign_unchecked<T: Signers + ?Sized>(
960        &mut self,
961        keypairs: &T,
962        positions: Vec<usize>,
963        recent_blockhash: Hash,
964    ) -> result::Result<(), SignerError> {
965        // if you change the blockhash, you're re-signing...
966        if recent_blockhash != self.message.recent_blockhash {
967            self.message.recent_blockhash = recent_blockhash;
968            self.signatures
969                .iter_mut()
970                .for_each(|signature| *signature = Signature::default());
971        }
972
973        let signatures = keypairs.try_sign_message(&self.message_data())?;
974        for i in 0..positions.len() {
975            self.signatures[positions[i]] = signatures[i];
976        }
977        Ok(())
978    }
979
980    /// Returns a signature that is not valid for signing this transaction.
981    pub fn get_invalid_signature() -> Signature {
982        Signature::default()
983    }
984
985    /// Verifies that all signers have signed the message.
986    ///
987    /// # Errors
988    ///
989    /// Returns [`TransactionError::SignatureFailure`] on error.
990    pub fn verify(&self) -> Result<()> {
991        let message_bytes = self.message_data();
992        if !self
993            ._verify_with_results(&message_bytes)
994            .iter()
995            .all(|verify_result| *verify_result)
996        {
997            Err(TransactionError::SignatureFailure)
998        } else {
999            Ok(())
1000        }
1001    }
1002
1003    /// Verify the transaction and hash its message.
1004    ///
1005    /// # Errors
1006    ///
1007    /// Returns [`TransactionError::SignatureFailure`] on error.
1008    pub fn verify_and_hash_message(&self) -> Result<Hash> {
1009        let message_bytes = self.message_data();
1010        if !self
1011            ._verify_with_results(&message_bytes)
1012            .iter()
1013            .all(|verify_result| *verify_result)
1014        {
1015            Err(TransactionError::SignatureFailure)
1016        } else {
1017            Ok(Message::hash_raw_message(&message_bytes))
1018        }
1019    }
1020
1021    /// Verifies that all signers have signed the message.
1022    ///
1023    /// Returns a vector with the length of required signatures, where each
1024    /// element is either `true` if that signer has signed, or `false` if not.
1025    pub fn verify_with_results(&self) -> Vec<bool> {
1026        self._verify_with_results(&self.message_data())
1027    }
1028
1029    pub(crate) fn _verify_with_results(&self, message_bytes: &[u8]) -> Vec<bool> {
1030        self.signatures
1031            .iter()
1032            .zip(&self.message.account_keys)
1033            .map(|(signature, pubkey)| signature.verify(pubkey.as_ref(), message_bytes))
1034            .collect()
1035    }
1036
1037    /// Verify the precompiled programs in this transaction.
1038    pub fn verify_precompiles(&self, feature_set: &feature_set::FeatureSet) -> Result<()> {
1039        for instruction in &self.message().instructions {
1040            // The Transaction may not be sanitized at this point
1041            if instruction.program_id_index as usize >= self.message().account_keys.len() {
1042                return Err(TransactionError::AccountNotFound);
1043            }
1044            let program_id = &self.message().account_keys[instruction.program_id_index as usize];
1045
1046            verify_if_precompile(
1047                program_id,
1048                instruction,
1049                &self.message().instructions,
1050                feature_set,
1051            )
1052            .map_err(|_| TransactionError::InvalidAccountIndex)?;
1053        }
1054        Ok(())
1055    }
1056
1057    /// Get the positions of the pubkeys in `account_keys` associated with signing keypairs.
1058    ///
1059    /// [`account_keys`]: Message::account_keys
1060    pub fn get_signing_keypair_positions(&self, pubkeys: &[Pubkey]) -> Result<Vec<Option<usize>>> {
1061        if self.message.account_keys.len() < self.message.header.num_required_signatures as usize {
1062            return Err(TransactionError::InvalidAccountIndex);
1063        }
1064        let signed_keys =
1065            &self.message.account_keys[0..self.message.header.num_required_signatures as usize];
1066
1067        Ok(pubkeys
1068            .iter()
1069            .map(|pubkey| signed_keys.iter().position(|x| x == pubkey))
1070            .collect())
1071    }
1072
1073    /// Replace all the signatures and pubkeys.
1074    pub fn replace_signatures(&mut self, signers: &[(Pubkey, Signature)]) -> Result<()> {
1075        let num_required_signatures = self.message.header.num_required_signatures as usize;
1076        if signers.len() != num_required_signatures
1077            || self.signatures.len() != num_required_signatures
1078            || self.message.account_keys.len() < num_required_signatures
1079        {
1080            return Err(TransactionError::InvalidAccountIndex);
1081        }
1082
1083        for (index, account_key) in self
1084            .message
1085            .account_keys
1086            .iter()
1087            .enumerate()
1088            .take(num_required_signatures)
1089        {
1090            if let Some((_pubkey, signature)) =
1091                signers.iter().find(|(key, _signature)| account_key == key)
1092            {
1093                self.signatures[index] = *signature
1094            } else {
1095                return Err(TransactionError::InvalidAccountIndex);
1096            }
1097        }
1098
1099        self.verify()
1100    }
1101
1102    pub fn is_signed(&self) -> bool {
1103        self.signatures
1104            .iter()
1105            .all(|signature| *signature != Signature::default())
1106    }
1107}
1108
1109/// Returns true if transaction begins with an advance nonce instruction.
1110pub fn uses_durable_nonce(tx: &Transaction) -> Option<&CompiledInstruction> {
1111    let message = tx.message();
1112    message
1113        .instructions
1114        .get(NONCED_TX_MARKER_IX_INDEX as usize)
1115        .filter(|instruction| {
1116            // Is system program
1117            matches!(
1118                message.account_keys.get(instruction.program_id_index as usize),
1119                Some(program_id) if system_program::check_id(program_id)
1120            )
1121            // Is a nonce advance instruction
1122            && matches!(
1123                limited_deserialize(&instruction.data),
1124                Ok(SystemInstruction::AdvanceNonceAccount)
1125            )
1126        })
1127}
1128
1129#[cfg(test)]
1130mod tests {
1131    #![allow(deprecated)]
1132
1133    use {
1134        super::*,
1135        crate::{
1136            hash::hash,
1137            instruction::AccountMeta,
1138            signature::{Keypair, Presigner, Signer},
1139            system_instruction,
1140        },
1141        bincode::{deserialize, serialize, serialized_size},
1142        std::mem::size_of,
1143    };
1144
1145    fn get_program_id(tx: &Transaction, instruction_index: usize) -> &Pubkey {
1146        let message = tx.message();
1147        let instruction = &message.instructions[instruction_index];
1148        instruction.program_id(&message.account_keys)
1149    }
1150
1151    #[test]
1152    fn test_refs() {
1153        let key = Keypair::new();
1154        let key1 = solana_sdk::pubkey::new_rand();
1155        let key2 = solana_sdk::pubkey::new_rand();
1156        let prog1 = solana_sdk::pubkey::new_rand();
1157        let prog2 = solana_sdk::pubkey::new_rand();
1158        let instructions = vec![
1159            CompiledInstruction::new(3, &(), vec![0, 1]),
1160            CompiledInstruction::new(4, &(), vec![0, 2]),
1161        ];
1162        let tx = Transaction::new_with_compiled_instructions(
1163            &[&key],
1164            &[key1, key2],
1165            Hash::default(),
1166            vec![prog1, prog2],
1167            instructions,
1168        );
1169        assert!(tx.sanitize().is_ok());
1170
1171        assert_eq!(tx.key(0, 0), Some(&key.pubkey()));
1172        assert_eq!(tx.signer_key(0, 0), Some(&key.pubkey()));
1173
1174        assert_eq!(tx.key(1, 0), Some(&key.pubkey()));
1175        assert_eq!(tx.signer_key(1, 0), Some(&key.pubkey()));
1176
1177        assert_eq!(tx.key(0, 1), Some(&key1));
1178        assert_eq!(tx.signer_key(0, 1), None);
1179
1180        assert_eq!(tx.key(1, 1), Some(&key2));
1181        assert_eq!(tx.signer_key(1, 1), None);
1182
1183        assert_eq!(tx.key(2, 0), None);
1184        assert_eq!(tx.signer_key(2, 0), None);
1185
1186        assert_eq!(tx.key(0, 2), None);
1187        assert_eq!(tx.signer_key(0, 2), None);
1188
1189        assert_eq!(*get_program_id(&tx, 0), prog1);
1190        assert_eq!(*get_program_id(&tx, 1), prog2);
1191    }
1192
1193    #[test]
1194    fn test_refs_invalid_program_id() {
1195        let key = Keypair::new();
1196        let instructions = vec![CompiledInstruction::new(1, &(), vec![])];
1197        let tx = Transaction::new_with_compiled_instructions(
1198            &[&key],
1199            &[],
1200            Hash::default(),
1201            vec![],
1202            instructions,
1203        );
1204        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1205    }
1206    #[test]
1207    fn test_refs_invalid_account() {
1208        let key = Keypair::new();
1209        let instructions = vec![CompiledInstruction::new(1, &(), vec![2])];
1210        let tx = Transaction::new_with_compiled_instructions(
1211            &[&key],
1212            &[],
1213            Hash::default(),
1214            vec![Pubkey::default()],
1215            instructions,
1216        );
1217        assert_eq!(*get_program_id(&tx, 0), Pubkey::default());
1218        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1219    }
1220
1221    #[test]
1222    fn test_sanitize_txs() {
1223        let key = Keypair::new();
1224        let id0 = Pubkey::default();
1225        let program_id = solana_sdk::pubkey::new_rand();
1226        let ix = Instruction::new_with_bincode(
1227            program_id,
1228            &0,
1229            vec![
1230                AccountMeta::new(key.pubkey(), true),
1231                AccountMeta::new(id0, true),
1232            ],
1233        );
1234        let mut tx = Transaction::new_with_payer(&[ix], Some(&key.pubkey()));
1235        let o = tx.clone();
1236        assert_eq!(tx.sanitize(), Ok(()));
1237        assert_eq!(tx.message.account_keys.len(), 3);
1238
1239        tx = o.clone();
1240        tx.message.header.num_required_signatures = 3;
1241        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1242
1243        tx = o.clone();
1244        tx.message.header.num_readonly_signed_accounts = 4;
1245        tx.message.header.num_readonly_unsigned_accounts = 0;
1246        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1247
1248        tx = o.clone();
1249        tx.message.header.num_readonly_signed_accounts = 2;
1250        tx.message.header.num_readonly_unsigned_accounts = 2;
1251        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1252
1253        tx = o.clone();
1254        tx.message.header.num_readonly_signed_accounts = 0;
1255        tx.message.header.num_readonly_unsigned_accounts = 4;
1256        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1257
1258        tx = o.clone();
1259        tx.message.instructions[0].program_id_index = 3;
1260        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1261
1262        tx = o.clone();
1263        tx.message.instructions[0].accounts[0] = 3;
1264        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1265
1266        tx = o.clone();
1267        tx.message.instructions[0].program_id_index = 0;
1268        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1269
1270        tx = o.clone();
1271        tx.message.header.num_readonly_signed_accounts = 2;
1272        tx.message.header.num_readonly_unsigned_accounts = 3;
1273        tx.message.account_keys.resize(4, Pubkey::default());
1274        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1275
1276        tx = o;
1277        tx.message.header.num_readonly_signed_accounts = 2;
1278        tx.message.header.num_required_signatures = 1;
1279        assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
1280    }
1281
1282    fn create_sample_transaction() -> Transaction {
1283        let keypair = Keypair::from_bytes(&[
1284            255, 101, 36, 24, 124, 23, 167, 21, 132, 204, 155, 5, 185, 58, 121, 75, 156, 227, 116,
1285            193, 215, 38, 142, 22, 8, 14, 229, 239, 119, 93, 5, 218, 36, 100, 158, 252, 33, 161,
1286            97, 185, 62, 89, 99, 195, 250, 249, 187, 189, 171, 118, 241, 90, 248, 14, 68, 219, 231,
1287            62, 157, 5, 142, 27, 210, 117,
1288        ])
1289        .unwrap();
1290        let to = Pubkey::from([
1291            1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4,
1292            1, 1, 1,
1293        ]);
1294
1295        let program_id = Pubkey::from([
1296            2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4,
1297            2, 2, 2,
1298        ]);
1299        let account_metas = vec![
1300            AccountMeta::new(keypair.pubkey(), true),
1301            AccountMeta::new(to, false),
1302        ];
1303        let instruction =
1304            Instruction::new_with_bincode(program_id, &(1u8, 2u8, 3u8), account_metas);
1305        let message = Message::new(&[instruction], Some(&keypair.pubkey()));
1306        let tx = Transaction::new(&[&keypair], message, Hash::default());
1307        tx.verify().expect("valid sample transaction signatures");
1308        tx
1309    }
1310
1311    #[test]
1312    fn test_transaction_serialize() {
1313        let tx = create_sample_transaction();
1314        let ser = serialize(&tx).unwrap();
1315        let deser = deserialize(&ser).unwrap();
1316        assert_eq!(tx, deser);
1317    }
1318
1319    /// Detect changes to the serialized size of payment transactions, which affects TPS.
1320    #[test]
1321    fn test_transaction_minimum_serialized_size() {
1322        let alice_keypair = Keypair::new();
1323        let alice_pubkey = alice_keypair.pubkey();
1324        let bob_pubkey = solana_sdk::pubkey::new_rand();
1325        let ix = system_instruction::transfer(&alice_pubkey, &bob_pubkey, 42);
1326
1327        let expected_data_size = size_of::<u32>() + size_of::<u64>();
1328        assert_eq!(expected_data_size, 12);
1329        assert_eq!(
1330            ix.data.len(),
1331            expected_data_size,
1332            "unexpected system instruction size"
1333        );
1334
1335        let expected_instruction_size = 1 + 1 + ix.accounts.len() + 1 + expected_data_size;
1336        assert_eq!(expected_instruction_size, 17);
1337
1338        let message = Message::new(&[ix], Some(&alice_pubkey));
1339        assert_eq!(
1340            serialized_size(&message.instructions[0]).unwrap() as usize,
1341            expected_instruction_size,
1342            "unexpected Instruction::serialized_size"
1343        );
1344
1345        let tx = Transaction::new(&[&alice_keypair], message, Hash::default());
1346
1347        let len_size = 1;
1348        let num_required_sigs_size = 1;
1349        let num_readonly_accounts_size = 2;
1350        let blockhash_size = size_of::<Hash>();
1351        let expected_transaction_size = len_size
1352            + (tx.signatures.len() * size_of::<Signature>())
1353            + num_required_sigs_size
1354            + num_readonly_accounts_size
1355            + len_size
1356            + (tx.message.account_keys.len() * size_of::<Pubkey>())
1357            + blockhash_size
1358            + len_size
1359            + expected_instruction_size;
1360        assert_eq!(expected_transaction_size, 215);
1361
1362        assert_eq!(
1363            serialized_size(&tx).unwrap() as usize,
1364            expected_transaction_size,
1365            "unexpected serialized transaction size"
1366        );
1367    }
1368
1369    /// Detect binary changes in the serialized transaction data, which could have a downstream
1370    /// affect on SDKs and applications
1371    #[test]
1372    fn test_sdk_serialize() {
1373        assert_eq!(
1374            serialize(&create_sample_transaction()).unwrap(),
1375            vec![
1376                1, 120, 138, 162, 185, 59, 209, 241, 157, 71, 157, 74, 131, 4, 87, 54, 28, 38, 180,
1377                222, 82, 64, 62, 61, 62, 22, 46, 17, 203, 187, 136, 62, 43, 11, 38, 235, 17, 239,
1378                82, 240, 139, 130, 217, 227, 214, 9, 242, 141, 223, 94, 29, 184, 110, 62, 32, 87,
1379                137, 63, 139, 100, 221, 20, 137, 4, 5, 1, 0, 1, 3, 36, 100, 158, 252, 33, 161, 97,
1380                185, 62, 89, 99, 195, 250, 249, 187, 189, 171, 118, 241, 90, 248, 14, 68, 219, 231,
1381                62, 157, 5, 142, 27, 210, 117, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9,
1382                9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1,
1383                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1384                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 1,
1385                3, 1, 2, 3
1386            ]
1387        );
1388    }
1389
1390    #[test]
1391    #[should_panic]
1392    fn test_transaction_missing_key() {
1393        let keypair = Keypair::new();
1394        let message = Message::new(&[], None);
1395        Transaction::new_unsigned(message).sign(&[&keypair], Hash::default());
1396    }
1397
1398    #[test]
1399    #[should_panic]
1400    fn test_partial_sign_mismatched_key() {
1401        let keypair = Keypair::new();
1402        let fee_payer = solana_sdk::pubkey::new_rand();
1403        let ix = Instruction::new_with_bincode(
1404            Pubkey::default(),
1405            &0,
1406            vec![AccountMeta::new(fee_payer, true)],
1407        );
1408        let message = Message::new(&[ix], Some(&fee_payer));
1409        Transaction::new_unsigned(message).partial_sign(&[&keypair], Hash::default());
1410    }
1411
1412    #[test]
1413    fn test_partial_sign() {
1414        let keypair0 = Keypair::new();
1415        let keypair1 = Keypair::new();
1416        let keypair2 = Keypair::new();
1417        let ix = Instruction::new_with_bincode(
1418            Pubkey::default(),
1419            &0,
1420            vec![
1421                AccountMeta::new(keypair0.pubkey(), true),
1422                AccountMeta::new(keypair1.pubkey(), true),
1423                AccountMeta::new(keypair2.pubkey(), true),
1424            ],
1425        );
1426        let message = Message::new(&[ix], Some(&keypair0.pubkey()));
1427        let mut tx = Transaction::new_unsigned(message);
1428
1429        tx.partial_sign(&[&keypair0, &keypair2], Hash::default());
1430        assert!(!tx.is_signed());
1431        tx.partial_sign(&[&keypair1], Hash::default());
1432        assert!(tx.is_signed());
1433
1434        let hash = hash(&[1]);
1435        tx.partial_sign(&[&keypair1], hash);
1436        assert!(!tx.is_signed());
1437        tx.partial_sign(&[&keypair0, &keypair2], hash);
1438        assert!(tx.is_signed());
1439    }
1440
1441    #[test]
1442    #[should_panic]
1443    fn test_transaction_missing_keypair() {
1444        let program_id = Pubkey::default();
1445        let keypair0 = Keypair::new();
1446        let id0 = keypair0.pubkey();
1447        let ix = Instruction::new_with_bincode(program_id, &0, vec![AccountMeta::new(id0, true)]);
1448        let message = Message::new(&[ix], Some(&id0));
1449        Transaction::new_unsigned(message).sign(&Vec::<&Keypair>::new(), Hash::default());
1450    }
1451
1452    #[test]
1453    #[should_panic]
1454    fn test_transaction_wrong_key() {
1455        let program_id = Pubkey::default();
1456        let keypair0 = Keypair::new();
1457        let wrong_id = Pubkey::default();
1458        let ix =
1459            Instruction::new_with_bincode(program_id, &0, vec![AccountMeta::new(wrong_id, true)]);
1460        let message = Message::new(&[ix], Some(&wrong_id));
1461        Transaction::new_unsigned(message).sign(&[&keypair0], Hash::default());
1462    }
1463
1464    #[test]
1465    fn test_transaction_correct_key() {
1466        let program_id = Pubkey::default();
1467        let keypair0 = Keypair::new();
1468        let id0 = keypair0.pubkey();
1469        let ix = Instruction::new_with_bincode(program_id, &0, vec![AccountMeta::new(id0, true)]);
1470        let message = Message::new(&[ix], Some(&id0));
1471        let mut tx = Transaction::new_unsigned(message);
1472        tx.sign(&[&keypair0], Hash::default());
1473        assert_eq!(
1474            tx.message.instructions[0],
1475            CompiledInstruction::new(1, &0, vec![0])
1476        );
1477        assert!(tx.is_signed());
1478    }
1479
1480    #[test]
1481    fn test_transaction_instruction_with_duplicate_keys() {
1482        let program_id = Pubkey::default();
1483        let keypair0 = Keypair::new();
1484        let id0 = keypair0.pubkey();
1485        let id1 = solana_sdk::pubkey::new_rand();
1486        let ix = Instruction::new_with_bincode(
1487            program_id,
1488            &0,
1489            vec![
1490                AccountMeta::new(id0, true),
1491                AccountMeta::new(id1, false),
1492                AccountMeta::new(id0, false),
1493                AccountMeta::new(id1, false),
1494            ],
1495        );
1496        let message = Message::new(&[ix], Some(&id0));
1497        let mut tx = Transaction::new_unsigned(message);
1498        tx.sign(&[&keypair0], Hash::default());
1499        assert_eq!(
1500            tx.message.instructions[0],
1501            CompiledInstruction::new(2, &0, vec![0, 1, 0, 1])
1502        );
1503        assert!(tx.is_signed());
1504    }
1505
1506    #[test]
1507    fn test_try_sign_dyn_keypairs() {
1508        let program_id = Pubkey::default();
1509        let keypair = Keypair::new();
1510        let pubkey = keypair.pubkey();
1511        let presigner_keypair = Keypair::new();
1512        let presigner_pubkey = presigner_keypair.pubkey();
1513
1514        let ix = Instruction::new_with_bincode(
1515            program_id,
1516            &0,
1517            vec![
1518                AccountMeta::new(pubkey, true),
1519                AccountMeta::new(presigner_pubkey, true),
1520            ],
1521        );
1522        let message = Message::new(&[ix], Some(&pubkey));
1523        let mut tx = Transaction::new_unsigned(message);
1524
1525        let presigner_sig = presigner_keypair.sign_message(&tx.message_data());
1526        let presigner = Presigner::new(&presigner_pubkey, &presigner_sig);
1527
1528        let signers: Vec<&dyn Signer> = vec![&keypair, &presigner];
1529
1530        let res = tx.try_sign(&signers, Hash::default());
1531        assert_eq!(res, Ok(()));
1532        assert_eq!(tx.signatures[0], keypair.sign_message(&tx.message_data()));
1533        assert_eq!(tx.signatures[1], presigner_sig);
1534
1535        // Wrong key should error, not panic
1536        let another_pubkey = solana_sdk::pubkey::new_rand();
1537        let ix = Instruction::new_with_bincode(
1538            program_id,
1539            &0,
1540            vec![
1541                AccountMeta::new(another_pubkey, true),
1542                AccountMeta::new(presigner_pubkey, true),
1543            ],
1544        );
1545        let message = Message::new(&[ix], Some(&another_pubkey));
1546        let mut tx = Transaction::new_unsigned(message);
1547
1548        let res = tx.try_sign(&signers, Hash::default());
1549        assert!(res.is_err());
1550        assert_eq!(
1551            tx.signatures,
1552            vec![Signature::default(), Signature::default()]
1553        );
1554    }
1555
1556    fn nonced_transfer_tx() -> (Pubkey, Pubkey, Transaction) {
1557        let from_keypair = Keypair::new();
1558        let from_pubkey = from_keypair.pubkey();
1559        let nonce_keypair = Keypair::new();
1560        let nonce_pubkey = nonce_keypair.pubkey();
1561        let instructions = [
1562            system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
1563            system_instruction::transfer(&from_pubkey, &nonce_pubkey, 42),
1564        ];
1565        let message = Message::new(&instructions, Some(&nonce_pubkey));
1566        let tx = Transaction::new(&[&from_keypair, &nonce_keypair], message, Hash::default());
1567        (from_pubkey, nonce_pubkey, tx)
1568    }
1569
1570    #[test]
1571    fn tx_uses_nonce_ok() {
1572        let (_, _, tx) = nonced_transfer_tx();
1573        assert!(uses_durable_nonce(&tx).is_some());
1574    }
1575
1576    #[test]
1577    fn tx_uses_nonce_empty_ix_fail() {
1578        assert!(uses_durable_nonce(&Transaction::default()).is_none());
1579    }
1580
1581    #[test]
1582    fn tx_uses_nonce_bad_prog_id_idx_fail() {
1583        let (_, _, mut tx) = nonced_transfer_tx();
1584        tx.message.instructions.get_mut(0).unwrap().program_id_index = 255u8;
1585        assert!(uses_durable_nonce(&tx).is_none());
1586    }
1587
1588    #[test]
1589    fn tx_uses_nonce_first_prog_id_not_nonce_fail() {
1590        let from_keypair = Keypair::new();
1591        let from_pubkey = from_keypair.pubkey();
1592        let nonce_keypair = Keypair::new();
1593        let nonce_pubkey = nonce_keypair.pubkey();
1594        let instructions = [
1595            system_instruction::transfer(&from_pubkey, &nonce_pubkey, 42),
1596            system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
1597        ];
1598        let message = Message::new(&instructions, Some(&from_pubkey));
1599        let tx = Transaction::new(&[&from_keypair, &nonce_keypair], message, Hash::default());
1600        assert!(uses_durable_nonce(&tx).is_none());
1601    }
1602
1603    #[test]
1604    fn tx_uses_nonce_wrong_first_nonce_ix_fail() {
1605        let from_keypair = Keypair::new();
1606        let from_pubkey = from_keypair.pubkey();
1607        let nonce_keypair = Keypair::new();
1608        let nonce_pubkey = nonce_keypair.pubkey();
1609        let instructions = [
1610            system_instruction::withdraw_nonce_account(
1611                &nonce_pubkey,
1612                &nonce_pubkey,
1613                &from_pubkey,
1614                42,
1615            ),
1616            system_instruction::transfer(&from_pubkey, &nonce_pubkey, 42),
1617        ];
1618        let message = Message::new(&instructions, Some(&nonce_pubkey));
1619        let tx = Transaction::new(&[&from_keypair, &nonce_keypair], message, Hash::default());
1620        assert!(uses_durable_nonce(&tx).is_none());
1621    }
1622
1623    #[test]
1624    fn tx_keypair_pubkey_mismatch() {
1625        let from_keypair = Keypair::new();
1626        let from_pubkey = from_keypair.pubkey();
1627        let to_pubkey = Pubkey::new_unique();
1628        let instructions = [system_instruction::transfer(&from_pubkey, &to_pubkey, 42)];
1629        let mut tx = Transaction::new_with_payer(&instructions, Some(&from_pubkey));
1630        let unused_keypair = Keypair::new();
1631        let err = tx
1632            .try_partial_sign(&[&from_keypair, &unused_keypair], Hash::default())
1633            .unwrap_err();
1634        assert_eq!(err, SignerError::KeypairPubkeyMismatch);
1635    }
1636
1637    #[test]
1638    fn test_unsized_signers() {
1639        fn instructions_to_tx(
1640            instructions: &[Instruction],
1641            signers: Box<dyn Signers>,
1642        ) -> Transaction {
1643            let pubkeys = signers.pubkeys();
1644            let first_signer = pubkeys.first().expect("should exist");
1645            let message = Message::new(instructions, Some(first_signer));
1646            Transaction::new(signers.as_ref(), message, Hash::default())
1647        }
1648
1649        let signer: Box<dyn Signer> = Box::new(Keypair::new());
1650        let tx = instructions_to_tx(&[], Box::new(vec![signer]));
1651
1652        assert!(tx.is_signed());
1653    }
1654
1655    #[test]
1656    fn test_replace_signatures() {
1657        let program_id = Pubkey::default();
1658        let keypair0 = Keypair::new();
1659        let keypair1 = Keypair::new();
1660        let pubkey0 = keypair0.pubkey();
1661        let pubkey1 = keypair1.pubkey();
1662        let ix = Instruction::new_with_bincode(
1663            program_id,
1664            &0,
1665            vec![
1666                AccountMeta::new(pubkey0, true),
1667                AccountMeta::new(pubkey1, true),
1668            ],
1669        );
1670        let message = Message::new(&[ix], Some(&pubkey0));
1671        let expected_account_keys = message.account_keys.clone();
1672        let mut tx = Transaction::new_unsigned(message);
1673        tx.sign(&[&keypair0, &keypair1], Hash::new_unique());
1674
1675        let signature0 = keypair0.sign_message(&tx.message_data());
1676        let signature1 = keypair1.sign_message(&tx.message_data());
1677
1678        // Replace signatures with order swapped
1679        tx.replace_signatures(&[(pubkey1, signature1), (pubkey0, signature0)])
1680            .unwrap();
1681        // Order of account_keys should not change
1682        assert_eq!(tx.message.account_keys, expected_account_keys);
1683        // Order of signatures should match original account_keys list
1684        assert_eq!(tx.signatures, &[signature0, signature1]);
1685    }
1686}