Demote write locks on transaction program ids (backport #19593) (#19633)

* Demote write locks on transaction program ids (#19593)

* Add feature

* Demote write lock on program ids

* Fixup bpf tests

* Update MappedMessage::is_writable

* Comma nit

* Review comments

(cherry picked from commit decec3cd8b)

# Conflicts:
#	core/src/banking_stage.rs
#	core/src/cost_model.rs
#	core/src/cost_tracker.rs
#	ledger-tool/src/main.rs
#	program-runtime/src/instruction_processor.rs
#	programs/bpf/tests/programs.rs
#	programs/bpf_loader/src/syscalls.rs
#	rpc/src/transaction_status_service.rs
#	runtime/src/accounts.rs
#	runtime/src/bank.rs
#	runtime/src/message_processor.rs
#	sdk/benches/serialize_instructions.rs
#	sdk/program/src/message/mapped.rs
#	sdk/program/src/message/sanitized.rs
#	sdk/src/transaction/sanitized.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
mergify[bot]
2021-09-04 06:46:09 +00:00
committed by GitHub
parent 2e4a2c15be
commit fcda5d4a7d
12 changed files with 227 additions and 160 deletions

View File

@@ -356,6 +356,16 @@ impl Message {
.collect()
}
pub fn is_key_called_as_program(&self, key_index: usize) -> bool {
if let Ok(key_index) = u8::try_from(key_index) {
self.instructions
.iter()
.any(|ix| ix.program_id_index == key_index)
} else {
false
}
}
pub fn is_key_passed_to_program(&self, index: usize) -> bool {
if let Ok(index) = u8::try_from(index) {
for ix in self.instructions.iter() {
@@ -391,7 +401,7 @@ impl Message {
self.program_position(i).is_some()
}
pub fn is_writable(&self, i: usize) -> bool {
pub fn is_writable(&self, i: usize, demote_program_write_locks: bool) -> bool {
(i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts)
as usize
|| (i >= self.header.num_required_signatures as usize
@@ -401,17 +411,21 @@ impl Message {
let key = self.account_keys[i];
sysvar::is_sysvar_id(&key) || BUILTIN_PROGRAMS_KEYS.contains(&key)
}
&& !(demote_program_write_locks && self.is_key_called_as_program(i))
}
pub fn is_signer(&self, i: usize) -> bool {
i < self.header.num_required_signatures as usize
}
pub fn get_account_keys_by_lock_type(&self) -> (Vec<&Pubkey>, Vec<&Pubkey>) {
pub fn get_account_keys_by_lock_type(
&self,
demote_program_write_locks: bool,
) -> (Vec<&Pubkey>, Vec<&Pubkey>) {
let mut writable_keys = vec![];
let mut readonly_keys = vec![];
for (i, key) in self.account_keys.iter().enumerate() {
if self.is_writable(i) {
if self.is_writable(i, demote_program_write_locks) {
writable_keys.push(key);
} else {
readonly_keys.push(key);
@@ -433,7 +447,7 @@ impl Message {
// 35..67 - program_id
// 67..69 - data len - u16
// 69..data_len - data
pub fn serialize_instructions(&self) -> Vec<u8> {
pub fn serialize_instructions(&self, demote_program_write_locks: bool) -> 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);
@@ -448,7 +462,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);
let is_writable = self.is_writable(account_index, demote_program_write_locks);
let mut meta_byte = 0;
if is_signer {
meta_byte |= 1 << Self::IS_SIGNER_BIT;
@@ -887,12 +901,13 @@ mod tests {
recent_blockhash: Hash::default(),
instructions: vec![],
};
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));
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));
}
#[test]
@@ -920,7 +935,7 @@ mod tests {
Some(&id1),
);
assert_eq!(
message.get_account_keys_by_lock_type(),
message.get_account_keys_by_lock_type(/*demote_program_write_locks=*/ true),
(vec![&id1, &id0], vec![&id3, &id2, &program_id])
);
}
@@ -950,7 +965,7 @@ mod tests {
];
let message = Message::new(&instructions, Some(&id1));
let serialized = message.serialize_instructions();
let serialized = message.serialize_instructions(/*demote_program_write_locks=*/ true);
for (i, instruction) in instructions.iter().enumerate() {
assert_eq!(
Message::deserialize_instruction(i, &serialized).unwrap(),
@@ -971,7 +986,7 @@ mod tests {
];
let message = Message::new(&instructions, Some(&id1));
let serialized = message.serialize_instructions();
let serialized = message.serialize_instructions(/*demote_program_write_locks=*/ true);
assert_eq!(
Message::deserialize_instruction(instructions.len(), &serialized).unwrap_err(),
SanitizeError::IndexOutOfBounds,