* `Bank::get_fee_for_message` is now nonce aware
(cherry picked from commit 4c577d7f8c
)
# Conflicts:
# runtime/src/bank.rs
# sdk/program/src/message/sanitized.rs
* Resolve conflicts
Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
@ -38,6 +38,7 @@ pub mod program_memory;
|
||||
pub mod program_option;
|
||||
pub mod program_pack;
|
||||
pub mod program_stubs;
|
||||
pub mod program_utils;
|
||||
pub mod pubkey;
|
||||
pub mod rent;
|
||||
pub mod sanitize;
|
||||
|
@ -2,10 +2,17 @@ use {
|
||||
crate::{
|
||||
hash::Hash,
|
||||
instruction::{CompiledInstruction, Instruction},
|
||||
message::{v0::{self, LoadedAddresses}, legacy::Message as LegacyMessage, MessageHeader},
|
||||
message::{
|
||||
legacy::Message as LegacyMessage,
|
||||
v0::{self, LoadedAddresses},
|
||||
MessageHeader,
|
||||
},
|
||||
nonce::NONCED_TX_MARKER_IX_INDEX,
|
||||
program_utils::limited_deserialize,
|
||||
pubkey::Pubkey,
|
||||
sanitize::{Sanitize, SanitizeError},
|
||||
serialize_utils::{append_slice, append_u16, append_u8},
|
||||
solana_program::{system_instruction::SystemInstruction, system_program},
|
||||
},
|
||||
bitflags::bitflags,
|
||||
std::convert::TryFrom,
|
||||
@ -288,6 +295,34 @@ impl SanitizedMessage {
|
||||
Self::V0(message) => message.is_upgradeable_loader_present(),
|
||||
}
|
||||
}
|
||||
|
||||
/// If the message uses a durable nonce, return the pubkey of the nonce account
|
||||
pub fn get_durable_nonce(&self, nonce_must_be_writable: bool) -> Option<&Pubkey> {
|
||||
self.instructions()
|
||||
.get(NONCED_TX_MARKER_IX_INDEX as usize)
|
||||
.filter(
|
||||
|ix| match self.get_account_key(ix.program_id_index as usize) {
|
||||
Some(program_id) => system_program::check_id(program_id),
|
||||
_ => false,
|
||||
},
|
||||
)
|
||||
.filter(|ix| {
|
||||
matches!(
|
||||
limited_deserialize(&ix.data, 4 /* serialized size of AdvanceNonceAccount */),
|
||||
Ok(SystemInstruction::AdvanceNonceAccount)
|
||||
)
|
||||
})
|
||||
.and_then(|ix| {
|
||||
ix.accounts.get(0).and_then(|idx| {
|
||||
let idx = *idx as usize;
|
||||
if nonce_must_be_writable && !self.is_writable(idx) {
|
||||
None
|
||||
} else {
|
||||
self.get_account_key(idx)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -311,9 +311,7 @@ mod tests {
|
||||
num_readonly_unsigned_accounts: 0,
|
||||
},
|
||||
recent_blockhash: Hash::new_unique(),
|
||||
account_keys: vec![
|
||||
Pubkey::new_unique(),
|
||||
],
|
||||
account_keys: vec![Pubkey::new_unique()],
|
||||
address_table_lookups: vec![
|
||||
MessageAddressTableLookup {
|
||||
account_key: Pubkey::new_unique(),
|
||||
|
@ -125,10 +125,7 @@ impl Message {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
super::*,
|
||||
crate::message::VersionedMessage,
|
||||
};
|
||||
use {super::*, crate::message::VersionedMessage};
|
||||
|
||||
#[test]
|
||||
fn test_sanitize() {
|
||||
@ -251,7 +248,6 @@ mod tests {
|
||||
.is_err());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_with_max_account_keys() {
|
||||
assert!(Message {
|
||||
|
38
sdk/program/src/program_utils.rs
Normal file
38
sdk/program/src/program_utils.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use {crate::instruction::InstructionError, bincode::config::Options};
|
||||
|
||||
/// Deserialize with a limit based the maximum amount of data a program can expect to get.
|
||||
/// This function should be used in place of direct deserialization to help prevent OOM errors
|
||||
pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
|
||||
where
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
bincode::options()
|
||||
.with_limit(limit)
|
||||
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
|
||||
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
|
||||
.deserialize_from(instruction_data)
|
||||
.map_err(|_| InstructionError::InvalidInstructionData)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use {super::*, solana_program::system_instruction::SystemInstruction};
|
||||
|
||||
#[test]
|
||||
fn test_limited_deserialize_advance_nonce_account() {
|
||||
let item = SystemInstruction::AdvanceNonceAccount;
|
||||
let serialized = bincode::serialize(&item).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
serialized.len(),
|
||||
4,
|
||||
"`SanitizedMessage::get_durable_nonce()` may need a change"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
|
||||
Ok(&item)
|
||||
);
|
||||
assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user