cbe_program/message/
mod.rs

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