diff --git a/Cargo.lock b/Cargo.lock index 2ed71fd23fe318..15f62950c56c04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5508,9 +5508,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e" +checksum = "debbc13545a1d972955a4fd3014e7c9d6d81da16c3626ee5f64bf3aa619548f8" dependencies = [ "byteorder", "combine", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index cf8592507e2e8b..33fcc45144bbca 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.7.0" } solana-faucet = { path = "../faucet", version = "=1.7.0" } solana-logger = { path = "../logger", version = "=1.7.0" } solana-net-utils = { path = "../net-utils", version = "=1.7.0" } -solana_rbpf = "=0.2.8" +solana_rbpf = "=0.2.9" solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.0" } solana-sdk = { path = "../sdk", version = "=1.7.0" } solana-stake-program = { path = "../programs/stake", version = "=1.7.0" } diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 9e73d4a6c07128..51a64075a5b371 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3637,9 +3637,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e" +checksum = "debbc13545a1d972955a4fd3014e7c9d6d81da16c3626ee5f64bf3aa619548f8" dependencies = [ "byteorder 1.3.4", "combine", diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index 284c28b490a23c..d2138569c5f74d 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -30,7 +30,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.7.0" } solana-cli-output = { path = "../../cli-output", version = "=1.7.0" } solana-logger = { path = "../../logger", version = "=1.7.0" } solana-measure = { path = "../../measure", version = "=1.7.0" } -solana_rbpf = "=0.2.8" +solana_rbpf = "=0.2.9" solana-runtime = { path = "../../runtime", version = "=1.7.0" } solana-sdk = { path = "../../sdk", version = "=1.7.0" } solana-transaction-status = { path = "../../transaction-status", version = "=1.7.0" } diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index a2c0515f123387..c8b3400254642f 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -20,7 +20,7 @@ sha3 = "0.9.1" solana-measure = { path = "../../measure", version = "=1.7.0" } solana-runtime = { path = "../../runtime", version = "=1.7.0" } solana-sdk = { path = "../../sdk", version = "=1.7.0" } -solana_rbpf = "=0.2.8" +solana_rbpf = "=0.2.9" thiserror = "1.0" [dev-dependencies] diff --git a/programs/bpf_loader/benches/serialization.rs b/programs/bpf_loader/benches/serialization.rs new file mode 100644 index 00000000000000..e99c953b496d4d --- /dev/null +++ b/programs/bpf_loader/benches/serialization.rs @@ -0,0 +1,141 @@ +#![feature(test)] + +extern crate test; + +use solana_bpf_loader_program::serialization::{ + serialize_parameters_aligned, serialize_parameters_unaligned, +}; +use solana_sdk::{ + account::{Account, AccountSharedData}, + bpf_loader, +}; +use solana_sdk::{keyed_account::KeyedAccount, pubkey::Pubkey}; +use std::cell::RefCell; +use test::Bencher; + +fn create_inputs() -> ( + Pubkey, + Vec, + Vec>, + Vec, +) { + let program_id = solana_sdk::pubkey::new_rand(); + let dup_key = solana_sdk::pubkey::new_rand(); + let dup_key2 = solana_sdk::pubkey::new_rand(); + let keys = vec![ + dup_key, + dup_key, + solana_sdk::pubkey::new_rand(), + solana_sdk::pubkey::new_rand(), + dup_key2, + dup_key2, + solana_sdk::pubkey::new_rand(), + solana_sdk::pubkey::new_rand(), + ]; + let accounts = vec![ + RefCell::new(AccountSharedData::from(Account { + lamports: 1, + data: vec![1u8, 2, 3, 4, 5], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 100, + })), + // dup + RefCell::new(AccountSharedData::from(Account { + lamports: 1, + data: vec![1u8; 100000], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 100, + })), + RefCell::new(AccountSharedData::from(Account { + lamports: 2, + data: vec![11u8; 100000], + owner: bpf_loader::id(), + executable: true, + rent_epoch: 200, + })), + RefCell::new(AccountSharedData::from(Account { + lamports: 3, + data: vec![], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 3100, + })), + RefCell::new(AccountSharedData::from(Account { + lamports: 4, + data: vec![1u8; 100000], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 100, + })), + // dup + RefCell::new(AccountSharedData::from(Account { + lamports: 4, + data: vec![1u8; 1000000], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 100, + })), + RefCell::new(AccountSharedData::from(Account { + lamports: 5, + data: vec![11u8; 10000], + owner: bpf_loader::id(), + executable: true, + rent_epoch: 200, + })), + RefCell::new(AccountSharedData::from(Account { + lamports: 6, + data: vec![], + owner: bpf_loader::id(), + executable: false, + rent_epoch: 3100, + })), + ]; + + let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + + (program_id, keys, accounts, instruction_data) +} + +#[bench] +fn bench_serialize_unaligned(bencher: &mut Bencher) { + let (program_id, keys, accounts, instruction_data) = create_inputs(); + let keyed_accounts: Vec<_> = keys + .iter() + .zip(&accounts) + .enumerate() + .map(|(i, (key, account))| { + if i <= accounts.len() / 2 { + KeyedAccount::new_readonly(&key, false, &account) + } else { + KeyedAccount::new(&key, false, &account) + } + }) + .collect(); + bencher.iter(|| { + let _ = serialize_parameters_unaligned(&program_id, &keyed_accounts, &instruction_data) + .unwrap(); + }); +} + +#[bench] +fn bench_serialize_aligned(bencher: &mut Bencher) { + let (program_id, keys, accounts, instruction_data) = create_inputs(); + let keyed_accounts: Vec<_> = keys + .iter() + .zip(&accounts) + .enumerate() + .map(|(i, (key, account))| { + if i <= accounts.len() / 2 { + KeyedAccount::new_readonly(&key, false, &account) + } else { + KeyedAccount::new(&key, false, &account) + } + }) + .collect(); + bencher.iter(|| { + let _ = + serialize_parameters_aligned(&program_id, &keyed_accounts, &instruction_data).unwrap(); + }); +} diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 5b0ef1af7fab3d..864440ebe5e638 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -148,7 +148,7 @@ pub fn create_vm<'a>( parameter_bytes: &mut [u8], invoke_context: &'a mut dyn InvokeContext, ) -> Result, EbpfError> { - let heap = AlignedMemory::new(DEFAULT_HEAP_SIZE, HOST_ALIGN); + let heap = AlignedMemory::new_with_size(DEFAULT_HEAP_SIZE, HOST_ALIGN); let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true); let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?; syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?; diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index 79b8564a39d1d0..31683274e5950b 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -231,7 +231,7 @@ pub fn serialize_parameters_aligned( .map_err(|_| InstructionError::InvalidArgument)?; v.write_all(&keyed_account.try_account_ref()?.data()) .map_err(|_| InstructionError::InvalidArgument)?; - v.fill( + v.resize( MAX_PERMITTED_DATA_INCREASE + (v.write_index() as *const u8).align_offset(align_of::()), 0, diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 456c400f27433c..31325ed8d008b5 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -2689,7 +2689,7 @@ mod tests { fn test_syscall_sol_alloc_free() { // large alloc { - let heap = AlignedMemory::new(100, HOST_ALIGN); + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( vec![MemoryRegion::new_from_slice( heap.as_slice(), @@ -2716,7 +2716,7 @@ mod tests { } // many small unaligned allocs { - let heap = AlignedMemory::new(100, HOST_ALIGN); + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( vec![MemoryRegion::new_from_slice( heap.as_slice(), @@ -2742,7 +2742,7 @@ mod tests { } // many small aligned allocs { - let heap = AlignedMemory::new(100, HOST_ALIGN); + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( vec![MemoryRegion::new_from_slice( heap.as_slice(), @@ -2769,7 +2769,7 @@ mod tests { // aligned allocs fn check_alignment() { - let heap = AlignedMemory::new(100, HOST_ALIGN); + let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( vec![MemoryRegion::new_from_slice( heap.as_slice(), @@ -2810,7 +2810,6 @@ mod tests { let bytes1 = "Gaggablaghblagh!"; let bytes2 = "flurbos"; - // lint warns field addr and len "never read" #[allow(dead_code)] struct MockSlice { pub addr: u64,