solana_message/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
3//! Sequences of [`Instruction`]s executed within a single transaction.
4//!
5//! [`Instruction`]: https://docs.rs/solana-instruction/latest/solana_instruction/struct.Instruction.html
6//!
7//! In Solana, programs execute instructions, and clients submit sequences
8//! of instructions to the network to be atomically executed as [`Transaction`]s.
9//!
10//! [`Transaction`]: https://docs.rs/solana-sdk/latest/solana-sdk/transaction/struct.Transaction.html
11//!
12//! A [`Message`] is the compact internal encoding of a transaction, as
13//! transmitted across the network and stored in, and operated on, by the
14//! runtime. It contains a flat array of all accounts accessed by all
15//! instructions in the message, a [`MessageHeader`] that describes the layout
16//! of that account array, a [recent blockhash], and a compact encoding of the
17//! message's instructions.
18//!
19//! [recent blockhash]: https://solana.com/docs/core/transactions#recent-blockhash
20//!
21//! Clients most often deal with `Instruction`s and `Transaction`s, with
22//! `Message`s being created by `Transaction` constructors.
23//!
24//! To ensure reliable network delivery, serialized messages must fit into the
25//! IPv6 MTU size, conservatively assumed to be 1280 bytes. Thus constrained,
26//! care must be taken in the amount of data consumed by instructions, and the
27//! number of accounts they require to function.
28//!
29//! This module defines two versions of `Message` in their own modules:
30//! [`legacy`] and [`v0`]. `legacy` is reexported here and is the current
31//! version as of Solana 1.10.0. `v0` is a [future message format] that encodes
32//! more account keys into a transaction than the legacy format. The
33//! [`VersionedMessage`] type is a thin wrapper around either message version.
34//!
35//! [future message format]: https://docs.solanalabs.com/proposals/versioned-transactions
36//!
37//! Despite living in the `solana-program` crate, there is no way to access the
38//! runtime's messages from within a Solana program, and only the legacy message
39//! types continue to be exposed to Solana programs, for backwards compatibility
40//! reasons.
41
42pub mod compiled_instruction;
43mod compiled_keys;
44pub mod inline_nonce;
45pub mod inner_instruction;
46pub mod legacy;
47#[cfg(feature = "serde")]
48use serde_derive::{Deserialize, Serialize};
49#[cfg(feature = "frozen-abi")]
50use solana_frozen_abi_macro::AbiExample;
51#[cfg(feature = "wincode")]
52use wincode::{SchemaRead, SchemaWrite};
53
54#[cfg(not(target_os = "solana"))]
55#[path = ""]
56mod non_bpf_modules {
57 mod account_keys;
58 mod address_loader;
59 mod sanitized;
60 mod versions;
61
62 pub use {account_keys::*, address_loader::*, sanitized::*, versions::*};
63}
64
65#[cfg(not(target_os = "solana"))]
66pub use non_bpf_modules::*;
67pub use {
68 compiled_keys::CompileError,
69 legacy::Message,
70 solana_address::Address,
71 solana_hash::Hash,
72 solana_instruction::{AccountMeta, Instruction},
73};
74
75/// The length of a message header in bytes.
76pub const MESSAGE_HEADER_LENGTH: usize = 3;
77
78/// Describes the organization of a `Message`'s account keys.
79///
80/// Every [`Instruction`] specifies which accounts it may reference, or
81/// otherwise requires specific permissions of. Those specifications are:
82/// whether the account is read-only, or read-write; and whether the account
83/// must have signed the transaction containing the instruction.
84///
85/// Whereas individual `Instruction`s contain a list of all accounts they may
86/// access, along with their required permissions, a `Message` contains a
87/// single shared flat list of _all_ accounts required by _all_ instructions in
88/// a transaction. When building a `Message`, this flat list is created and
89/// `Instruction`s are converted to [`CompiledInstruction`]s. Those
90/// `CompiledInstruction`s then reference by index the accounts they require in
91/// the single shared account list.
92///
93/// [`Instruction`]: https://docs.rs/solana-instruction/latest/solana_instruction/struct.Instruction.html
94/// [`CompiledInstruction`]: crate::compiled_instruction::CompiledInstruction
95///
96/// The shared account list is ordered by the permissions required of the accounts:
97///
98/// - accounts that are writable and signers
99/// - accounts that are read-only and signers
100/// - accounts that are writable and not signers
101/// - accounts that are read-only and not signers
102///
103/// Given this ordering, the fields of `MessageHeader` describe which accounts
104/// in a transaction require which permissions.
105///
106/// When multiple transactions access the same read-only accounts, the runtime
107/// may process them in parallel, in a single [PoH] entry. Transactions that
108/// access the same read-write accounts are processed sequentially.
109///
110/// [PoH]: https://docs.solanalabs.com/consensus/synchronization
111#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
112#[cfg_attr(
113 feature = "serde",
114 derive(Deserialize, Serialize),
115 serde(rename_all = "camelCase")
116)]
117#[cfg_attr(
118 feature = "wincode",
119 derive(SchemaWrite, SchemaRead),
120 wincode(struct_extensions)
121)]
122#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
123pub struct MessageHeader {
124 /// The number of signatures required for this message to be considered
125 /// valid. The signers of those signatures must match the first
126 /// `num_required_signatures` of [`Message::account_keys`].
127 // NOTE: Serialization-related changes must be paired with the direct read at sigverify.
128 pub num_required_signatures: u8,
129
130 /// The last `num_readonly_signed_accounts` of the signed keys are read-only
131 /// accounts.
132 pub num_readonly_signed_accounts: u8,
133
134 /// The last `num_readonly_unsigned_accounts` of the unsigned keys are
135 /// read-only accounts.
136 pub num_readonly_unsigned_accounts: u8,
137}
138
139/// The definition of address lookup table accounts.
140///
141/// As used by the `crate::v0` message format.
142#[derive(Debug, PartialEq, Eq, Clone)]
143pub struct AddressLookupTableAccount {
144 pub key: Address,
145 pub addresses: Vec<Address>,
146}