Pass the correct program_id to programs (#8630)

This commit is contained in:
Jack May 2020-03-05 10:57:35 -08:00 committed by GitHub
parent 97c5fb8141
commit 5e3ce30d02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 25 deletions

View File

@ -4,7 +4,8 @@
extern crate solana_sdk; extern crate solana_sdk;
use solana_sdk::{ use solana_sdk::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, info, log::*, pubkey::Pubkey, account_info::AccountInfo, bpf_loader, entrypoint, entrypoint::ProgramResult, info, log::*,
pubkey::Pubkey,
}; };
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -28,6 +29,8 @@ fn process_instruction(
info!("Program identifier:"); info!("Program identifier:");
program_id.log(); program_id.log();
assert!(!bpf_loader::check_id(program_id));
// Log the provided account keys and instruction input data. In the case of // Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real // the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work. // programs will have specific requirements so they can do their work.

View File

@ -9,6 +9,7 @@ use num_derive::{FromPrimitive, ToPrimitive};
use solana_rbpf::{memory_region::MemoryRegion, EbpfVm}; use solana_rbpf::{memory_region::MemoryRegion, EbpfVm};
use solana_sdk::{ use solana_sdk::{
account::KeyedAccount, account::KeyedAccount,
bpf_loader,
entrypoint::SUCCESS, entrypoint::SUCCESS,
instruction::InstructionError, instruction::InstructionError,
loader_instruction::LoaderInstruction, loader_instruction::LoaderInstruction,
@ -147,6 +148,8 @@ pub fn process_instruction(
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
solana_logger::setup_with_default("solana=info"); solana_logger::setup_with_default("solana=info");
debug_assert!(bpf_loader::check_id(program_id));
if keyed_accounts.is_empty() { if keyed_accounts.is_empty() {
warn!("No account keys"); warn!("No account keys");
return Err(InstructionError::NotEnoughAccountKeys); return Err(InstructionError::NotEnoughAccountKeys);
@ -164,8 +167,11 @@ pub fn process_instruction(
} }
}; };
let parameter_accounts = keyed_accounts_iter.as_slice(); let parameter_accounts = keyed_accounts_iter.as_slice();
let parameter_bytes = let parameter_bytes = serialize_parameters(
serialize_parameters(program_id, parameter_accounts, &instruction_data)?; program.unsigned_key(),
parameter_accounts,
&instruction_data,
)?;
info!("Call BPF program"); info!("Call BPF program");
match vm.execute_program(parameter_bytes.as_slice(), &[], &[heap_region]) { match vm.execute_program(parameter_bytes.as_slice(), &[], &[heap_region]) {
@ -265,13 +271,13 @@ mod tests {
// Case: Empty keyed accounts // Case: Empty keyed accounts
assert_eq!( assert_eq!(
Err(InstructionError::NotEnoughAccountKeys), Err(InstructionError::NotEnoughAccountKeys),
process_instruction(&program_id, &vec![], &instruction_data) process_instruction(&bpf_loader::id(), &vec![], &instruction_data)
); );
// Case: Not signed // Case: Not signed
assert_eq!( assert_eq!(
Err(InstructionError::MissingRequiredSignature), Err(InstructionError::MissingRequiredSignature),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
// Case: Write bytes to an offset // Case: Write bytes to an offset
@ -279,7 +285,7 @@ mod tests {
keyed_accounts[0].account.borrow_mut().data = vec![0; 6]; keyed_accounts[0].account.borrow_mut().data = vec![0; 6];
assert_eq!( assert_eq!(
Ok(()), Ok(()),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
assert_eq!( assert_eq!(
vec![0, 0, 0, 1, 2, 3], vec![0, 0, 0, 1, 2, 3],
@ -291,7 +297,7 @@ mod tests {
keyed_accounts[0].account.borrow_mut().data = vec![0; 5]; keyed_accounts[0].account.borrow_mut().data = vec![0; 5];
assert_eq!( assert_eq!(
Err(InstructionError::AccountDataTooSmall), Err(InstructionError::AccountDataTooSmall),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
} }
@ -312,7 +318,7 @@ mod tests {
// Case: Empty keyed accounts // Case: Empty keyed accounts
assert_eq!( assert_eq!(
Err(InstructionError::NotEnoughAccountKeys), Err(InstructionError::NotEnoughAccountKeys),
process_instruction(&program_id, &vec![], &instruction_data) process_instruction(&bpf_loader::id(), &vec![], &instruction_data)
); );
let rent_account = RefCell::new(rent::create_account(1, &rent)); let rent_account = RefCell::new(rent::create_account(1, &rent));
@ -321,7 +327,7 @@ mod tests {
// Case: Not signed // Case: Not signed
assert_eq!( assert_eq!(
Err(InstructionError::MissingRequiredSignature), Err(InstructionError::MissingRequiredSignature),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
// Case: Finalize // Case: Finalize
@ -331,7 +337,7 @@ mod tests {
]; ];
assert_eq!( assert_eq!(
Ok(()), Ok(()),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
assert!(keyed_accounts[0].account.borrow().executable); assert!(keyed_accounts[0].account.borrow().executable);
@ -345,7 +351,7 @@ mod tests {
]; ];
assert_eq!( assert_eq!(
Err(InstructionError::InvalidAccountData), Err(InstructionError::InvalidAccountData),
process_instruction(&program_id, &keyed_accounts, &instruction_data) process_instruction(&bpf_loader::id(), &keyed_accounts, &instruction_data)
); );
} }
@ -369,20 +375,20 @@ mod tests {
// Case: Empty keyed accounts // Case: Empty keyed accounts
assert_eq!( assert_eq!(
Err(InstructionError::NotEnoughAccountKeys), Err(InstructionError::NotEnoughAccountKeys),
process_instruction(&program_id, &vec![], &vec![]) process_instruction(&bpf_loader::id(), &vec![], &vec![])
); );
// Case: Only a program account // Case: Only a program account
assert_eq!( assert_eq!(
Ok(()), Ok(()),
process_instruction(&program_id, &keyed_accounts, &vec![]) process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
); );
// Case: Account not executable // Case: Account not executable
keyed_accounts[0].account.borrow_mut().executable = false; keyed_accounts[0].account.borrow_mut().executable = false;
assert_eq!( assert_eq!(
Err(InstructionError::InvalidInstructionData), Err(InstructionError::InvalidInstructionData),
process_instruction(&program_id, &keyed_accounts, &vec![]) process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
); );
keyed_accounts[0].account.borrow_mut().executable = true; keyed_accounts[0].account.borrow_mut().executable = true;
@ -391,7 +397,7 @@ mod tests {
keyed_accounts.push(KeyedAccount::new(&program_key, false, &parameter_account)); keyed_accounts.push(KeyedAccount::new(&program_key, false, &parameter_account));
assert_eq!( assert_eq!(
Ok(()), Ok(()),
process_instruction(&program_id, &keyed_accounts, &vec![]) process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
); );
// Case: With duplicate accounts // Case: With duplicate accounts
@ -402,7 +408,7 @@ mod tests {
keyed_accounts.push(KeyedAccount::new(&duplicate_key, false, &parameter_account)); keyed_accounts.push(KeyedAccount::new(&duplicate_key, false, &parameter_account));
assert_eq!( assert_eq!(
Ok(()), Ok(()),
process_instruction(&program_id, &keyed_accounts, &vec![]) process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
); );
} }
} }

View File

@ -4884,10 +4884,13 @@ mod tests {
let mut bank = Bank::new(&genesis_config); let mut bank = Bank::new(&genesis_config);
fn mock_vote_processor( fn mock_vote_processor(
_pubkey: &Pubkey, program_id: &Pubkey,
_ka: &[KeyedAccount], _keyed_accounts: &[KeyedAccount],
_data: &[u8], _instruction_data: &[u8],
) -> std::result::Result<(), InstructionError> { ) -> std::result::Result<(), InstructionError> {
if !solana_vote_program::check_id(program_id) {
return Err(InstructionError::IncorrectProgramId);
}
Err(InstructionError::CustomError(42)) Err(InstructionError::CustomError(42))
} }

View File

@ -6,6 +6,7 @@ use solana_sdk::{
entrypoint_native, entrypoint_native,
instruction::{CompiledInstruction, InstructionError}, instruction::{CompiledInstruction, InstructionError},
message::Message, message::Message,
native_loader::id as native_loader_id,
pubkey::Pubkey, pubkey::Pubkey,
system_program, system_program,
transaction::TransactionError, transaction::TransactionError,
@ -172,7 +173,6 @@ impl MessageProcessor {
executable_accounts: &[(Pubkey, RefCell<Account>)], executable_accounts: &[(Pubkey, RefCell<Account>)],
program_accounts: &[Rc<RefCell<Account>>], program_accounts: &[Rc<RefCell<Account>>],
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let program_id = instruction.program_id(&message.account_keys);
let mut keyed_accounts = create_keyed_readonly_accounts(executable_accounts); let mut keyed_accounts = create_keyed_readonly_accounts(executable_accounts);
let mut keyed_accounts2: Vec<_> = instruction let mut keyed_accounts2: Vec<_> = instruction
.accounts .accounts
@ -202,12 +202,16 @@ impl MessageProcessor {
let root_program_id = keyed_accounts[0].unsigned_key(); let root_program_id = keyed_accounts[0].unsigned_key();
for (id, process_instruction) in &self.instruction_processors { for (id, process_instruction) in &self.instruction_processors {
if id == root_program_id { if id == root_program_id {
return process_instruction(&program_id, &keyed_accounts[1..], &instruction.data); return process_instruction(
&root_program_id,
&keyed_accounts[1..],
&instruction.data,
);
} }
} }
native_loader::invoke_entrypoint( native_loader::invoke_entrypoint(
&program_id, &native_loader_id(),
&keyed_accounts, &keyed_accounts,
&instruction.data, &instruction.data,
&self.symbol_cache, &self.symbol_cache,

View File

@ -83,7 +83,7 @@ fn library_open(path: &PathBuf) -> std::io::Result<Library> {
} }
pub fn invoke_entrypoint( pub fn invoke_entrypoint(
program_id: &Pubkey, _program_id: &Pubkey,
keyed_accounts: &[KeyedAccount], keyed_accounts: &[KeyedAccount],
instruction_data: &[u8], instruction_data: &[u8],
symbol_cache: &SymbolCache, symbol_cache: &SymbolCache,
@ -94,7 +94,7 @@ pub fn invoke_entrypoint(
let name_vec = &program.try_account_ref()?.data; let name_vec = &program.try_account_ref()?.data;
if let Some(entrypoint) = symbol_cache.read().unwrap().get(name_vec) { if let Some(entrypoint) = symbol_cache.read().unwrap().get(name_vec) {
unsafe { unsafe {
return entrypoint(program_id, params, instruction_data); return entrypoint(names[0].unsigned_key(), params, instruction_data);
} }
} }
let name = match str::from_utf8(name_vec) { let name = match str::from_utf8(name_vec) {
@ -120,7 +120,7 @@ pub fn invoke_entrypoint(
return Err(NativeLoaderError::EntrypointNotFound.into()); return Err(NativeLoaderError::EntrypointNotFound.into());
} }
}; };
let ret = entrypoint(program_id, params, instruction_data); let ret = entrypoint(names[0].unsigned_key(), params, instruction_data);
symbol_cache symbol_cache
.write() .write()
.unwrap() .unwrap()

View File

@ -3,6 +3,10 @@
use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey}; use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey};
// Prototype of a native program entry point // Prototype of a native program entry point
///
/// program_id: Program ID of the currently executing program
/// keyed_accounts: Accounts passed as part of the instruction
/// instruction_data: Instruction data
pub type Entrypoint = unsafe extern "C" fn( pub type Entrypoint = unsafe extern "C" fn(
program_id: &Pubkey, program_id: &Pubkey,
keyed_accounts: &[KeyedAccount], keyed_accounts: &[KeyedAccount],