Clean up demote program write lock feature (#21949)

* Clean up demote program write lock feature

* fix test
This commit is contained in:
Justin Starry
2021-12-16 17:27:22 -05:00
committed by GitHub
parent a5769c029f
commit 6ff0be6a82
19 changed files with 98 additions and 204 deletions

View File

@ -19,8 +19,6 @@ fn make_instructions() -> Vec<Instruction> {
vec![inst; 4]
}
const DEMOTE_PROGRAM_WRITE_LOCKS: bool = true;
#[bench]
fn bench_bincode_instruction_serialize(b: &mut Bencher) {
let instructions = make_instructions();
@ -36,7 +34,7 @@ fn bench_manual_instruction_serialize(b: &mut Bencher) {
SanitizedMessage::try_from(Message::new(&instructions, Some(&Pubkey::new_unique())))
.unwrap();
b.iter(|| {
test::black_box(message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS));
test::black_box(message.serialize_instructions());
});
}
@ -55,7 +53,7 @@ fn bench_manual_instruction_deserialize(b: &mut Bencher) {
let message =
SanitizedMessage::try_from(Message::new(&instructions, Some(&Pubkey::new_unique())))
.unwrap();
let serialized = message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS);
let serialized = message.serialize_instructions();
b.iter(|| {
for i in 0..instructions.len() {
#[allow(deprecated)]
@ -70,7 +68,7 @@ fn bench_manual_instruction_deserialize_single(b: &mut Bencher) {
let message =
SanitizedMessage::try_from(Message::new(&instructions, Some(&Pubkey::new_unique())))
.unwrap();
let serialized = message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS);
let serialized = message.serialize_instructions();
b.iter(|| {
#[allow(deprecated)]
test::black_box(instructions::load_instruction_at(3, &serialized).unwrap());

View File

@ -367,10 +367,9 @@ impl Message {
self.program_position(i).is_some()
}
pub fn is_writable(&self, i: usize, demote_program_write_locks: bool) -> bool {
let demote_program_id = demote_program_write_locks
&& self.is_key_called_as_program(i)
&& !self.is_upgradeable_loader_present();
pub fn is_writable(&self, i: usize) -> bool {
let demote_program_id =
self.is_key_called_as_program(i) && !self.is_upgradeable_loader_present();
(i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts)
as usize
|| (i >= self.header.num_required_signatures as usize
@ -392,7 +391,7 @@ impl Message {
let mut writable_keys = vec![];
let mut readonly_keys = vec![];
for (i, key) in self.account_keys.iter().enumerate() {
if self.is_writable(i, /*demote_program_write_locks=*/ true) {
if self.is_writable(i) {
writable_keys.push(key);
} else {
readonly_keys.push(key);
@ -430,8 +429,7 @@ impl Message {
for account_index in &instruction.accounts {
let account_index = *account_index as usize;
let is_signer = self.is_signer(account_index);
let is_writable =
self.is_writable(account_index, /*demote_program_write_locks=*/ true);
let is_writable = self.is_writable(account_index);
let mut meta_byte = 0;
if is_signer {
meta_byte |= 1 << Self::IS_SIGNER_BIT;
@ -894,13 +892,12 @@ mod tests {
recent_blockhash: Hash::default(),
instructions: vec![],
};
let demote_program_write_locks = true;
assert!(message.is_writable(0, demote_program_write_locks));
assert!(!message.is_writable(1, demote_program_write_locks));
assert!(!message.is_writable(2, demote_program_write_locks));
assert!(message.is_writable(3, demote_program_write_locks));
assert!(message.is_writable(4, demote_program_write_locks));
assert!(!message.is_writable(5, demote_program_write_locks));
assert!(message.is_writable(0));
assert!(!message.is_writable(1));
assert!(!message.is_writable(2));
assert!(message.is_writable(3));
assert!(message.is_writable(4));
assert!(!message.is_writable(5));
}
#[test]

View File

@ -187,10 +187,10 @@ impl SanitizedMessage {
/// Returns true if the account at the specified index is writable by the
/// instructions in this message.
pub fn is_writable(&self, index: usize, demote_program_write_locks: bool) -> bool {
pub fn is_writable(&self, index: usize) -> bool {
match self {
Self::Legacy(message) => message.is_writable(index, demote_program_write_locks),
Self::V0(message) => message.is_writable(index, demote_program_write_locks),
Self::Legacy(message) => message.is_writable(index),
Self::V0(message) => message.is_writable(index),
}
}
@ -214,7 +214,7 @@ impl SanitizedMessage {
// 67..69 - data len - u16
// 69..data_len - data
#[allow(clippy::integer_arithmetic)]
pub fn serialize_instructions(&self, demote_program_write_locks: bool) -> Vec<u8> {
pub fn serialize_instructions(&self) -> Vec<u8> {
// 64 bytes is a reasonable guess, calculating exactly is slower in benchmarks
let mut data = Vec::with_capacity(self.instructions().len() * (32 * 2));
append_u16(&mut data, self.instructions().len() as u16);
@ -229,7 +229,7 @@ impl SanitizedMessage {
for account_index in &instruction.accounts {
let account_index = *account_index as usize;
let is_signer = self.is_signer(account_index);
let is_writable = self.is_writable(account_index, demote_program_write_locks);
let is_writable = self.is_writable(account_index);
let mut account_meta = InstructionsSysvarAccountMeta::NONE;
if is_signer {
account_meta |= InstructionsSysvarAccountMeta::IS_SIGNER;
@ -426,10 +426,9 @@ mod tests {
),
];
let demote_program_write_locks = true;
let message = LegacyMessage::new(&instructions, Some(&id1));
let sanitized_message = SanitizedMessage::try_from(message.clone()).unwrap();
let serialized = sanitized_message.serialize_instructions(demote_program_write_locks);
let serialized = sanitized_message.serialize_instructions();
// assert that SanitizedMessage::serialize_instructions has the same behavior as the
// deprecated Message::serialize_instructions method

View File

@ -104,11 +104,10 @@ impl LoadedMessage {
}
/// Returns true if the account at the specified index was loaded as writable
pub fn is_writable(&self, key_index: usize, demote_program_write_locks: bool) -> bool {
pub fn is_writable(&self, key_index: usize) -> bool {
if self.is_writable_index(key_index) {
if let Some(key) = self.get_account_key(key_index) {
let demote_program_id = demote_program_write_locks
&& self.is_key_called_as_program(key_index)
let demote_program_id = self.is_key_called_as_program(key_index)
&& !self.is_upgradeable_loader_present();
return !(sysvar::is_sysvar_id(key)
|| BUILTIN_PROGRAMS_KEYS.contains(key)
@ -269,11 +268,11 @@ mod tests {
message.message.account_keys[0] = sysvar::clock::id();
assert!(message.is_writable_index(0));
assert!(!message.is_writable(0, /*demote_program_write_locks=*/ true));
assert!(!message.is_writable(0));
message.message.account_keys[0] = system_program::id();
assert!(message.is_writable_index(0));
assert!(!message.is_writable(0, /*demote_program_write_locks=*/ true));
assert!(!message.is_writable(0));
}
#[test]
@ -303,6 +302,6 @@ mod tests {
};
assert!(message.is_writable_index(2));
assert!(!message.is_writable(2, /*demote_program_write_locks=*/ true));
assert!(!message.is_writable(2));
}
}

View File

@ -13,11 +13,8 @@ crate::declare_sysvar_id!("Sysvar1nstructions1111111111111111111111111", Instruc
// Construct the account data for the Instruction sSysvar
#[cfg(not(target_arch = "bpf"))]
pub fn construct_instructions_data(
message: &crate::message::SanitizedMessage,
demote_program_write_locks: bool,
) -> Vec<u8> {
let mut data = message.serialize_instructions(demote_program_write_locks);
pub fn construct_instructions_data(message: &crate::message::SanitizedMessage) -> Vec<u8> {
let mut data = message.serialize_instructions();
// add room for current instruction index.
data.resize(data.len() + 2, 0);
@ -154,7 +151,7 @@ mod tests {
let key = id();
let mut lamports = 0;
let mut data = construct_instructions_data(&sanitized_message, true);
let mut data = construct_instructions_data(&sanitized_message);
let owner = crate::sysvar::id();
let mut account_info = AccountInfo::new(
&key,
@ -208,7 +205,7 @@ mod tests {
let key = id();
let mut lamports = 0;
let mut data = construct_instructions_data(&sanitized_message, true);
let mut data = construct_instructions_data(&sanitized_message);
store_current_index(&mut data, 1);
let owner = crate::sysvar::id();
let mut account_info = AccountInfo::new(
@ -266,7 +263,7 @@ mod tests {
let key = id();
let mut lamports = 0;
let mut data = construct_instructions_data(&sanitized_message, true);
let mut data = construct_instructions_data(&sanitized_message);
store_current_index(&mut data, 1);
let owner = crate::sysvar::id();
let mut account_info = AccountInfo::new(

View File

@ -410,7 +410,7 @@ pub fn uses_durable_nonce(tx: &Transaction) -> Option<&CompiledInstruction> {
// Nonce account is writable
&& matches!(
instruction.accounts.get(0),
Some(index) if message.is_writable(*index as usize, true)
Some(index) if message.is_writable(*index as usize)
)
})
}

View File

@ -140,7 +140,7 @@ impl SanitizedTransaction {
}
/// Return the list of accounts that must be locked during processing this transaction.
pub fn get_account_locks(&self, demote_program_write_locks: bool) -> TransactionAccountLocks {
pub fn get_account_locks(&self) -> TransactionAccountLocks {
let message = &self.message;
let num_readonly_accounts = message.num_readonly_accounts();
let num_writable_accounts = message
@ -153,7 +153,7 @@ impl SanitizedTransaction {
};
for (i, key) in message.account_keys_iter().enumerate() {
if message.is_writable(i, demote_program_write_locks) {
if message.is_writable(i) {
account_locks.writable.push(key);
} else {
account_locks.readonly.push(key);
@ -183,7 +183,7 @@ impl SanitizedTransaction {
.and_then(|ix| {
ix.accounts.get(0).and_then(|idx| {
let idx = *idx as usize;
if nonce_must_be_writable && !self.message.is_writable(idx, true) {
if nonce_must_be_writable && !self.message.is_writable(idx) {
None
} else {
self.message.get_account_key(idx)