pub struct Message {
pub header: MessageHeader,
pub account_keys: Vec<Pubkey>,
pub recent_blockhash: Hash,
pub instructions: Vec<CompiledInstruction>,
}
Expand description
A Solana transaction message (legacy).
See the message
module 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: MessageHeader
The message header, identifying signed and read-only account_keys
.
account_keys: Vec<Pubkey>
All the account keys used by this transaction.
recent_blockhash: Hash
The 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<&Pubkey>) -> Message
pub fn new(instructions: &[Instruction], payer: Option<&Pubkey>) -> 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_rpc_client::rpc_client::RpcClient;
use solana_sdk::{
instruction::Instruction,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
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: Pubkey,
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<&Pubkey>,
blockhash: &Hash,
) -> Message
pub fn new_with_blockhash( instructions: &[Instruction], payer: Option<&Pubkey>, 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_rpc_client::rpc_client::RpcClient;
use solana_sdk::{
instruction::Instruction,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
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: Pubkey,
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], tx.message.recent_blockhash);
client.send_and_confirm_transaction(&tx)?;
Ok(())
}
sourcepub fn new_with_nonce(
instructions: Vec<Instruction>,
payer: Option<&Pubkey>,
nonce_account_pubkey: &Pubkey,
nonce_authority_pubkey: &Pubkey,
) -> Message
pub fn new_with_nonce( instructions: Vec<Instruction>, payer: Option<&Pubkey>, nonce_account_pubkey: &Pubkey, nonce_authority_pubkey: &Pubkey, ) -> 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_rpc_client::rpc_client::RpcClient;
use solana_sdk::{
hash::Hash,
instruction::Instruction,
message::Message,
nonce,
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction,
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 },
}
// 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: Pubkey,
payer: &Keypair
) -> Result<(Transaction, Pubkey)> {
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<Pubkey>
{
let nonce_account_address = Keypair::new();
let nonce_account_size = nonce::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 = system_instruction::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<Pubkey>, recent_blockhash: Hash, instructions: Vec<CompiledInstruction>, ) -> Message
sourcepub fn hash_raw_message(message_bytes: &[u8]) -> Hash
pub fn hash_raw_message(message_bytes: &[u8]) -> Hash
Compute the blake3 hash of a raw transaction message.
pub fn compile_instruction(&self, ix: &Instruction) -> CompiledInstruction
pub fn serialize(&self) -> Vec<u8> ⓘ
pub fn program_id(&self, instruction_index: usize) -> Option<&Pubkey>
pub fn program_index(&self, instruction_index: usize) -> Option<usize>
pub fn program_ids(&self) -> Vec<&Pubkey>
pub fn is_key_passed_to_program(&self, key_index: usize) -> bool
pub fn is_key_called_as_program(&self, key_index: usize) -> bool
pub fn is_non_loader_key(&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
pub fn is_writable(&self, i: usize) -> bool
pub fn is_signer(&self, i: usize) -> bool
pub fn get_account_keys_by_lock_type(&self) -> (Vec<&Pubkey>, Vec<&Pubkey>)
pub fn deserialize_instruction( index: usize, data: &[u8], ) -> Result<Instruction, SanitizeError>
pub fn signer_keys(&self) -> Vec<&Pubkey>
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>,
source§impl FromWasmAbi for Message
impl FromWasmAbi for Message
source§impl IntoWasmAbi for Message
impl IntoWasmAbi for Message
source§impl LongRefFromWasmAbi for Message
impl LongRefFromWasmAbi for Message
source§impl OptionFromWasmAbi for Message
impl OptionFromWasmAbi for Message
source§impl OptionIntoWasmAbi for Message
impl OptionIntoWasmAbi for Message
source§impl RefFromWasmAbi for Message
impl RefFromWasmAbi for Message
source§type Anchor = RcRef<Message>
type Anchor = RcRef<Message>
Self
for the duration of the
invocation of the function that has an &Self
parameter. This is
required to ensure that the lifetimes don’t persist beyond one function
call, and so that they remain anonymous.source§unsafe fn ref_from_abi(
js: <Message as RefFromWasmAbi>::Abi,
) -> <Message as RefFromWasmAbi>::Anchor
unsafe fn ref_from_abi( js: <Message as RefFromWasmAbi>::Abi, ) -> <Message as RefFromWasmAbi>::Anchor
source§impl RefMutFromWasmAbi for Message
impl RefMutFromWasmAbi for Message
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,
source§impl TryFrom<Message> for SanitizedMessage
impl TryFrom<Message> for SanitizedMessage
source§type Error = SanitizeMessageError
type Error = SanitizeMessageError
source§fn try_from(
message: Message,
) -> Result<SanitizedMessage, <SanitizedMessage as TryFrom<Message>>::Error>
fn try_from( message: Message, ) -> Result<SanitizedMessage, <SanitizedMessage as TryFrom<Message>>::Error>
source§impl TryFromJsValue for Message
impl TryFromJsValue for Message
source§impl VectorFromWasmAbi for Message
impl VectorFromWasmAbi for Message
type Abi = <Box<[JsValue]> as FromWasmAbi>::Abi
unsafe fn vector_from_abi( js: <Message as VectorFromWasmAbi>::Abi, ) -> Box<[Message]>
source§impl VectorIntoWasmAbi for Message
impl VectorIntoWasmAbi for Message
type Abi = <Box<[JsValue]> as IntoWasmAbi>::Abi
fn vector_into_abi( vector: Box<[Message]>, ) -> <Message as VectorIntoWasmAbi>::Abi
impl Eq for Message
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 UnwindSafe for Message
Blanket Implementations§
source§impl<T> AbiEnumVisitor for T
impl<T> AbiEnumVisitor for T
default fn visit_for_abi( &self, _digester: &mut AbiDigester, ) -> Result<AbiDigester, DigestError>
source§impl<T> AbiEnumVisitor for T
impl<T> AbiEnumVisitor for T
default fn visit_for_abi( &self, digester: &mut AbiDigester, ) -> Result<AbiDigester, DigestError>
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§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
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 moresource§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<T> ReturnWasmAbi for Twhere
T: IntoWasmAbi,
impl<T> ReturnWasmAbi for Twhere
T: IntoWasmAbi,
source§type Abi = <T as IntoWasmAbi>::Abi
type Abi = <T as IntoWasmAbi>::Abi
IntoWasmAbi::Abi
source§fn return_abi(self) -> <T as ReturnWasmAbi>::Abi
fn return_abi(self) -> <T as ReturnWasmAbi>::Abi
IntoWasmAbi::into_abi
, except that it may throw and never
return in the case of Err
.