pub struct Message {
pub header: MessageHeader,
pub account_keys: Vec<Address>,
pub recent_blockhash: Hash,
pub instructions: Vec<CompiledInstruction>,
}Expand description
A Solana transaction message (legacy).
See the crate documentation for further description.
Some constructors accept an optional payer, the account responsible for
paying the cost of executing a transaction. In most cases, callers should
specify the payer explicitly in these constructors. In some cases though,
the caller is not required to specify the payer, but is still allowed to:
in the Message structure, the first account is always the fee-payer, so if
the caller has knowledge that the first account of the constructed
transaction’s Message is both a signer and the expected fee-payer, then
redundantly specifying the fee-payer is not strictly required.
Fields§
§header: MessageHeaderThe message header, identifying signed and read-only account_keys.
account_keys: Vec<Address>All the account keys used by this transaction.
recent_blockhash: HashThe id of a recent ledger entry.
instructions: Vec<CompiledInstruction>Programs that will be executed in sequence and committed in one atomic transaction if all succeed.
Implementations§
Source§impl Message
impl Message
Sourcepub fn new(instructions: &[Instruction], payer: Option<&Address>) -> Message
pub fn new(instructions: &[Instruction], payer: Option<&Address>) -> Message
Create a new Message.
§Examples
This example uses the solana_sdk, solana_rpc_client and anyhow crates.
use anyhow::Result;
use borsh::{BorshSerialize, BorshDeserialize};
use solana_instruction::Instruction;
use solana_keypair::Keypair;
use solana_message::Message;
use solana_address::Address;
use solana_rpc_client::rpc_client::RpcClient;
use solana_signer::Signer;
use solana_transaction::Transaction;
// A custom program instruction. This would typically be defined in
// another crate so it can be shared between the on-chain program and
// the client.
#[derive(BorshSerialize, BorshDeserialize)]
enum BankInstruction {
Initialize,
Deposit { lamports: u64 },
Withdraw { lamports: u64 },
}
fn send_initialize_tx(
client: &RpcClient,
program_id: Address,
payer: &Keypair
) -> Result<()> {
let bank_instruction = BankInstruction::Initialize;
let instruction = Instruction::new_with_borsh(
program_id,
&bank_instruction,
vec![],
);
let message = Message::new(
&[instruction],
Some(&payer.pubkey()),
);
let blockhash = client.get_latest_blockhash()?;
let mut tx = Transaction::new(&[payer], message, blockhash);
client.send_and_confirm_transaction(&tx)?;
Ok(())
}Sourcepub fn new_with_blockhash(
instructions: &[Instruction],
payer: Option<&Address>,
blockhash: &Hash,
) -> Message
pub fn new_with_blockhash( instructions: &[Instruction], payer: Option<&Address>, blockhash: &Hash, ) -> Message
Create a new message while setting the blockhash.
§Examples
This example uses the solana_sdk, solana_rpc_client and anyhow crates.
use anyhow::Result;
use borsh::{BorshSerialize, BorshDeserialize};
use solana_instruction::Instruction;
use solana_keypair::Keypair;
use solana_message::Message;
use solana_address::Address;
use solana_rpc_client::rpc_client::RpcClient;
use solana_signer::Signer;
use solana_transaction::Transaction;
// A custom program instruction. This would typically be defined in
// another crate so it can be shared between the on-chain program and
// the client.
#[derive(BorshSerialize, BorshDeserialize)]
enum BankInstruction {
Initialize,
Deposit { lamports: u64 },
Withdraw { lamports: u64 },
}
fn send_initialize_tx(
client: &RpcClient,
program_id: Address,
payer: &Keypair
) -> Result<()> {
let bank_instruction = BankInstruction::Initialize;
let instruction = Instruction::new_with_borsh(
program_id,
&bank_instruction,
vec![],
);
let blockhash = client.get_latest_blockhash()?;
let message = Message::new_with_blockhash(
&[instruction],
Some(&payer.pubkey()),
&blockhash,
);
let mut tx = Transaction::new_unsigned(message);
tx.sign(&[payer], blockhash);
client.send_and_confirm_transaction(&tx)?;
Ok(())
}Sourcepub fn new_with_nonce(
instructions: Vec<Instruction>,
payer: Option<&Address>,
nonce_account_pubkey: &Address,
nonce_authority_pubkey: &Address,
) -> Message
pub fn new_with_nonce( instructions: Vec<Instruction>, payer: Option<&Address>, nonce_account_pubkey: &Address, nonce_authority_pubkey: &Address, ) -> Message
Create a new message for a nonced transaction.
In this type of transaction, the blockhash is replaced with a durable transaction nonce, allowing for extended time to pass between the transaction’s signing and submission to the blockchain.
§Examples
This example uses the solana_sdk, solana_rpc_client and anyhow crates.
use anyhow::Result;
use borsh::{BorshSerialize, BorshDeserialize};
use solana_hash::Hash;
use solana_instruction::Instruction;
use solana_keypair::Keypair;
use solana_message::Message;
use solana_address::Address;
use solana_rpc_client::rpc_client::RpcClient;
use solana_signer::Signer;
use solana_transaction::Transaction;
use solana_system_interface::instruction::create_nonce_account;
// A custom program instruction. This would typically be defined in
// another crate so it can be shared between the on-chain program and
// the client.
#[derive(BorshSerialize, BorshDeserialize)]
enum BankInstruction {
Initialize,
Deposit { lamports: u64 },
Withdraw { lamports: u64 },
}
// Create a nonced transaction for later signing and submission,
// returning it and the nonce account's pubkey.
fn create_offline_initialize_tx(
client: &RpcClient,
program_id: Address,
payer: &Keypair
) -> Result<(Transaction, Address)> {
let bank_instruction = BankInstruction::Initialize;
let bank_instruction = Instruction::new_with_borsh(
program_id,
&bank_instruction,
vec![],
);
// This will create a nonce account and assign authority to the
// payer so they can sign to advance the nonce and withdraw its rent.
let nonce_account = make_nonce_account(client, payer)?;
let mut message = Message::new_with_nonce(
vec![bank_instruction],
Some(&payer.pubkey()),
&nonce_account,
&payer.pubkey()
);
// This transaction will need to be signed later, using the blockhash
// stored in the nonce account.
let tx = Transaction::new_unsigned(message);
Ok((tx, nonce_account))
}
fn make_nonce_account(client: &RpcClient, payer: &Keypair)
-> Result<Address>
{
let nonce_account_address = Keypair::new();
let nonce_account_size = solana_nonce::state::State::size();
let nonce_rent = client.get_minimum_balance_for_rent_exemption(nonce_account_size)?;
// Assigning the nonce authority to the payer so they can sign for the withdrawal,
// and we can throw away the nonce address secret key.
let create_nonce_instr = create_nonce_account(
&payer.pubkey(),
&nonce_account_address.pubkey(),
&payer.pubkey(),
nonce_rent,
);
let mut nonce_tx = Transaction::new_with_payer(&create_nonce_instr, Some(&payer.pubkey()));
let blockhash = client.get_latest_blockhash()?;
nonce_tx.sign(&[&payer, &nonce_account_address], blockhash);
client.send_and_confirm_transaction(&nonce_tx)?;
Ok(nonce_account_address.pubkey())
}pub fn new_with_compiled_instructions( num_required_signatures: u8, num_readonly_signed_accounts: u8, num_readonly_unsigned_accounts: u8, account_keys: Vec<Address>, recent_blockhash: Hash, instructions: Vec<CompiledInstruction>, ) -> Message
pub fn compile_instruction(&self, ix: &Instruction) -> CompiledInstruction
pub fn serialize(&self) -> Vec<u8> ⓘ
pub fn program_id(&self, instruction_index: usize) -> Option<&Address>
pub fn program_index(&self, instruction_index: usize) -> Option<usize>
pub fn program_ids(&self) -> Vec<&Address>
Sourcepub fn is_instruction_account(&self, key_index: usize) -> bool
pub fn is_instruction_account(&self, key_index: usize) -> bool
Returns true if the account at the specified index is an account input to some program instruction in this message.
pub fn is_key_called_as_program(&self, key_index: usize) -> bool
pub fn program_position(&self, index: usize) -> Option<usize>
pub fn maybe_executable(&self, i: usize) -> bool
pub fn demote_program_id(&self, i: usize) -> bool
Sourcepub fn is_maybe_writable(
&self,
i: usize,
reserved_account_keys: Option<&HashSet<Address>>,
) -> bool
pub fn is_maybe_writable( &self, i: usize, reserved_account_keys: Option<&HashSet<Address>>, ) -> bool
Returns true if the account at the specified index is writable by the
instructions in this message. The reserved_account_keys param has been
optional to allow clients to approximate writability without requiring
fetching the latest set of reserved account keys. If this method is
called by the runtime, the latest set of reserved account keys must be
passed.
pub fn is_signer(&self, i: usize) -> bool
pub fn signer_keys(&self) -> Vec<&Address>
Sourcepub fn has_duplicates(&self) -> bool
pub fn has_duplicates(&self) -> bool
Returns true if account_keys has any duplicate keys.
Sourcepub fn is_upgradeable_loader_present(&self) -> bool
pub fn is_upgradeable_loader_present(&self) -> bool
Returns true if any account is the BPF upgradeable loader.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Message
impl<'de> Deserialize<'de> for Message
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<Message, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<Message, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
impl Eq for Message
Source§impl<'de, WincodeConfig> SchemaRead<'de, WincodeConfig> for Messagewhere
WincodeConfig: Config,
impl<'de, WincodeConfig> SchemaRead<'de, WincodeConfig> for Messagewhere
WincodeConfig: Config,
Source§impl<'de, C> SchemaReadContext<'de, C, u8> for Messagewhere
C: Config,
Available on crate feature wincode only.
impl<'de, C> SchemaReadContext<'de, C, u8> for Messagewhere
C: Config,
wincode only.type Dst = Message
Source§fn read_with_context(
num_required_signatures: u8,
reader: impl Reader<'de>,
dst: &mut MaybeUninit<<Message as SchemaReadContext<'de, C, u8>>::Dst>,
) -> Result<(), ReadError>
fn read_with_context( num_required_signatures: u8, reader: impl Reader<'de>, dst: &mut MaybeUninit<<Message as SchemaReadContext<'de, C, u8>>::Dst>, ) -> Result<(), ReadError>
Source§impl<WincodeConfig> SchemaWrite<WincodeConfig> for Messagewhere
WincodeConfig: Config,
impl<WincodeConfig> SchemaWrite<WincodeConfig> for Messagewhere
WincodeConfig: Config,
type Src = Message
Source§fn size_of(
src: &<Message as SchemaWrite<WincodeConfig>>::Src,
) -> Result<usize, WriteError>
fn size_of( src: &<Message as SchemaWrite<WincodeConfig>>::Src, ) -> Result<usize, WriteError>
Self::Src. Read moreSource§fn write(
writer: impl Writer,
src: &<Message as SchemaWrite<WincodeConfig>>::Src,
) -> Result<(), WriteError>
fn write( writer: impl Writer, src: &<Message as SchemaWrite<WincodeConfig>>::Src, ) -> Result<(), WriteError>
Self::Src to writer.Source§impl Serialize for Message
impl Serialize for Message
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl StructuralPartialEq for Message
Auto Trait Implementations§
impl Freeze for Message
impl RefUnwindSafe for Message
impl Send for Message
impl Sync for Message
impl Unpin for Message
impl UnsafeUnpin for Message
impl UnwindSafe for Message
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<'de, T, C> Deserialize<'de, C> for Twhere
C: Config,
T: SchemaRead<'de, C>,
impl<'de, T, C> Deserialize<'de, C> for Twhere
C: Config,
T: SchemaRead<'de, C>,
Source§impl<'de, T> Deserialize<'de> for Twhere
T: SchemaRead<'de, Configuration>,
impl<'de, T> Deserialize<'de> for Twhere
T: SchemaRead<'de, Configuration>,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> DeserializeOwned for Twhere
T: SchemaReadOwned<Configuration>,
impl<T> DeserializeOwned for Twhere
T: SchemaReadOwned<Configuration>,
Source§fn deserialize_from<'de>(src: impl Reader<'de>) -> Result<Self::Dst, ReadError>
fn deserialize_from<'de>(src: impl Reader<'de>) -> Result<Self::Dst, ReadError>
Reader into a new Self::Dst.Source§fn deserialize_from_into<'de>(
src: impl Reader<'de>,
dst: &mut MaybeUninit<Self::Dst>,
) -> Result<(), ReadError>
fn deserialize_from_into<'de>( src: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>, ) -> Result<(), ReadError>
Reader into dst.Source§impl<T, C> DeserializeOwned<C> for Twhere
C: Config,
T: SchemaReadOwned<C>,
impl<T, C> DeserializeOwned<C> for Twhere
C: Config,
T: SchemaReadOwned<C>,
Source§fn deserialize_from<'de>(src: impl Reader<'de>) -> Result<Self::Dst, ReadError>
fn deserialize_from<'de>(src: impl Reader<'de>) -> Result<Self::Dst, ReadError>
Reader into a new Self::Dst.Source§fn deserialize_from_into<'de>(
src: impl Reader<'de>,
dst: &mut MaybeUninit<Self::Dst>,
) -> Result<(), ReadError>
fn deserialize_from_into<'de>( src: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>, ) -> Result<(), ReadError>
Reader into dst.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSendSync for T
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T, C> SchemaReadOwned<C> for Twhere
C: ConfigCore,
T: for<'de> SchemaRead<'de, C>,
Source§impl<T> Serialize for T
impl<T> Serialize for T
Source§fn serialize(src: &Self::Src) -> Result<Vec<u8>, WriteError>
fn serialize(src: &Self::Src) -> Result<Vec<u8>, WriteError>
Vec of bytes.Source§fn serialize_into(dst: impl Writer, src: &Self::Src) -> Result<(), WriteError>
fn serialize_into(dst: impl Writer, src: &Self::Src) -> Result<(), WriteError>
Source§fn serialized_size(src: &Self::Src) -> Result<u64, WriteError>
fn serialized_size(src: &Self::Src) -> Result<u64, WriteError>
Source§impl<T, C> Serialize<C> for T
impl<T, C> Serialize<C> for T
Source§fn serialize(src: &Self::Src, config: C) -> Result<Vec<u8>, WriteError>
fn serialize(src: &Self::Src, config: C) -> Result<Vec<u8>, WriteError>
Vec of bytes.Source§fn serialize_into(
dst: impl Writer,
src: &Self::Src,
config: C,
) -> Result<(), WriteError>
fn serialize_into( dst: impl Writer, src: &Self::Src, config: C, ) -> Result<(), WriteError>
Writer.