* 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 commitdecec3cd8b
) # 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> (cherry picked from commitfcda5d4a7d
) # Conflicts: # cli-output/src/display.rs # core/src/transaction_status_service.rs # program-test/src/lib.rs # programs/bpf_loader/src/syscalls.rs # runtime/src/accounts.rs # runtime/src/bank.rs # runtime/src/message_processor.rs # sdk/benches/serialize_instructions.rs # sdk/program/src/message.rs # sdk/src/feature_set.rs # transaction-status/src/parse_accounts.rs * Replace feature and fix conflicts Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
@@ -14,6 +14,8 @@ 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();
|
||||
@@ -27,9 +29,7 @@ fn bench_manual_instruction_serialize(b: &mut Bencher) {
|
||||
let instructions = make_instructions();
|
||||
let message = Message::new(&instructions, None);
|
||||
b.iter(|| {
|
||||
test::black_box(message.serialize_instructions(
|
||||
true, // demote_sysvar_write_locks
|
||||
));
|
||||
test::black_box(message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -46,9 +46,7 @@ fn bench_bincode_instruction_deserialize(b: &mut Bencher) {
|
||||
fn bench_manual_instruction_deserialize(b: &mut Bencher) {
|
||||
let instructions = make_instructions();
|
||||
let message = Message::new(&instructions, None);
|
||||
let serialized = message.serialize_instructions(
|
||||
true, // demote_sysvar_write_locks
|
||||
);
|
||||
let serialized = message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS);
|
||||
b.iter(|| {
|
||||
for i in 0..instructions.len() {
|
||||
test::black_box(instructions::load_instruction_at(i, &serialized).unwrap());
|
||||
@@ -60,9 +58,7 @@ fn bench_manual_instruction_deserialize(b: &mut Bencher) {
|
||||
fn bench_manual_instruction_deserialize_single(b: &mut Bencher) {
|
||||
let instructions = make_instructions();
|
||||
let message = Message::new(&instructions, None);
|
||||
let serialized = message.serialize_instructions(
|
||||
true, // demote_sysvar_write_locks
|
||||
);
|
||||
let serialized = message.serialize_instructions(DEMOTE_PROGRAM_WRITE_LOCKS);
|
||||
b.iter(|| {
|
||||
test::black_box(instructions::load_instruction_at(3, &serialized).unwrap());
|
||||
});
|
||||
|
@@ -337,6 +337,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() {
|
||||
@@ -363,7 +373,7 @@ impl Message {
|
||||
self.program_position(i).is_some()
|
||||
}
|
||||
|
||||
pub fn is_writable(&self, i: usize, demote_sysvar_write_locks: bool) -> 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
|
||||
@@ -371,9 +381,9 @@ impl Message {
|
||||
- self.header.num_readonly_unsigned_accounts as usize))
|
||||
&& !{
|
||||
let key = self.account_keys[i];
|
||||
demote_sysvar_write_locks
|
||||
&& (sysvar::is_sysvar_id(&key) || BUILTIN_PROGRAMS_KEYS.contains(&key))
|
||||
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 {
|
||||
@@ -382,12 +392,12 @@ impl Message {
|
||||
|
||||
pub fn get_account_keys_by_lock_type(
|
||||
&self,
|
||||
demote_sysvar_write_locks: bool,
|
||||
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, demote_sysvar_write_locks) {
|
||||
if self.is_writable(i, demote_program_write_locks) {
|
||||
writable_keys.push(key);
|
||||
} else {
|
||||
readonly_keys.push(key);
|
||||
@@ -409,7 +419,7 @@ impl Message {
|
||||
// 35..67 - program_id
|
||||
// 67..69 - data len - u16
|
||||
// 69..data_len - data
|
||||
pub fn serialize_instructions(&self, demote_sysvar_write_locks: bool) -> 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);
|
||||
@@ -424,7 +434,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_sysvar_write_locks);
|
||||
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;
|
||||
@@ -863,13 +873,13 @@ mod tests {
|
||||
recent_blockhash: Hash::default(),
|
||||
instructions: vec![],
|
||||
};
|
||||
let demote_sysvar_write_locks = true;
|
||||
assert_eq!(message.is_writable(0, demote_sysvar_write_locks), true);
|
||||
assert_eq!(message.is_writable(1, demote_sysvar_write_locks), false);
|
||||
assert_eq!(message.is_writable(2, demote_sysvar_write_locks), false);
|
||||
assert_eq!(message.is_writable(3, demote_sysvar_write_locks), true);
|
||||
assert_eq!(message.is_writable(4, demote_sysvar_write_locks), true);
|
||||
assert_eq!(message.is_writable(5, demote_sysvar_write_locks), false);
|
||||
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]
|
||||
@@ -897,9 +907,7 @@ mod tests {
|
||||
Some(&id1),
|
||||
);
|
||||
assert_eq!(
|
||||
message.get_account_keys_by_lock_type(
|
||||
true, // demote_sysvar_write_locks
|
||||
),
|
||||
message.get_account_keys_by_lock_type(/*demote_program_write_locks=*/ true),
|
||||
(vec![&id1, &id0], vec![&id3, &id2, &program_id])
|
||||
);
|
||||
}
|
||||
@@ -929,9 +937,7 @@ mod tests {
|
||||
];
|
||||
|
||||
let message = Message::new(&instructions, Some(&id1));
|
||||
let serialized = message.serialize_instructions(
|
||||
true, // demote_sysvar_write_locks
|
||||
);
|
||||
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(),
|
||||
@@ -952,9 +958,7 @@ mod tests {
|
||||
];
|
||||
|
||||
let message = Message::new(&instructions, Some(&id1));
|
||||
let serialized = message.serialize_instructions(
|
||||
true, // demote_sysvar_write_locks
|
||||
);
|
||||
let serialized = message.serialize_instructions(/*demote_program_write_locks=*/ true);
|
||||
assert_eq!(
|
||||
Message::deserialize_instruction(instructions.len(), &serialized).unwrap_err(),
|
||||
SanitizeError::IndexOutOfBounds,
|
||||
|
@@ -107,10 +107,6 @@ pub mod upgradeable_close_instruction {
|
||||
solana_sdk::declare_id!("FsPaByos3gA9bUEhp3EimQpQPCoSvCEigHod496NmABQ");
|
||||
}
|
||||
|
||||
pub mod demote_sysvar_write_locks {
|
||||
solana_sdk::declare_id!("86LJYRuq2zgtHuL3FccR6hqFJQMQkFoun4knAxcPiF1P");
|
||||
}
|
||||
|
||||
pub mod sysvar_via_syscall {
|
||||
solana_sdk::declare_id!("7411E6gFQLDhQkdRjmpXwM1hzHMMoYQUjHicmvGPC1Nf");
|
||||
}
|
||||
@@ -170,6 +166,10 @@ pub mod spl_token_v2_set_authority_fix {
|
||||
solana_sdk::declare_id!("FToKNBYyiF4ky9s8WsmLBXHCht17Ek7RXaLZGHzzQhJ1");
|
||||
}
|
||||
|
||||
pub mod demote_program_write_locks {
|
||||
solana_sdk::declare_id!("3E3jV7v9VcdJL8iYZUMax9DiDno8j7EWUVbhm9RtShj2");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
@@ -195,7 +195,6 @@ lazy_static! {
|
||||
(require_stake_for_gossip::id(), "require stakes for propagating crds values through gossip #15561"),
|
||||
(cpi_data_cost::id(), "charge the compute budget for data passed via CPI"),
|
||||
(upgradeable_close_instruction::id(), "close upgradeable buffer accounts"),
|
||||
(demote_sysvar_write_locks::id(), "demote builtins and sysvar write locks to readonly #15497"),
|
||||
(sysvar_via_syscall::id(), "provide sysvars via syscalls"),
|
||||
(check_duplicates_by_hash::id(), "use transaction message hash for duplicate check"),
|
||||
(enforce_aligned_host_addrs::id(), "enforce aligned host addresses"),
|
||||
@@ -211,6 +210,7 @@ lazy_static! {
|
||||
(libsecp256k1_0_5_upgrade_enabled::id(), "upgrade libsecp256k1 to v0.5.0"),
|
||||
(merge_nonce_error_into_system_error::id(), "merge NonceError into SystemError"),
|
||||
(spl_token_v2_set_authority_fix::id(), "spl-token set_authority fix"),
|
||||
(demote_program_write_locks::id(), "demote program write locks to readonly #19593"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
Reference in New Issue
Block a user