Add LoaderInstruction::InvokeMain (#5116)
* Remove unreachable, untested runtime check * tx_data -> ix_data * Add LoaderInstruction::InvokeMain * Add test and allow loaders to be registered statically. * Fix clippy error
This commit is contained in:
@ -85,47 +85,17 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) {
|
||||
pub fn process_instruction(
|
||||
program_id: &Pubkey,
|
||||
keyed_accounts: &mut [KeyedAccount],
|
||||
tx_data: &[u8],
|
||||
ix_data: &[u8],
|
||||
) -> Result<(), InstructionError> {
|
||||
solana_logger::setup();
|
||||
|
||||
if keyed_accounts[0].account.executable {
|
||||
let (progs, params) = keyed_accounts.split_at_mut(1);
|
||||
let prog = &progs[0].account.data;
|
||||
info!("Call BPF program");
|
||||
let (mut vm, heap_region) = match create_vm(prog) {
|
||||
Ok(info) => info,
|
||||
Err(e) => {
|
||||
warn!("Failed to create BPF VM: {}", e);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
};
|
||||
let mut v = serialize_parameters(program_id, params, &tx_data);
|
||||
|
||||
match vm.execute_program(v.as_mut_slice(), &[], &[heap_region]) {
|
||||
Ok(status) => {
|
||||
if 0 == status {
|
||||
warn!("BPF program failed: {}", status);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("BPF VM failed to run program: {}", e);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
}
|
||||
deserialize_parameters(params, &v);
|
||||
info!(
|
||||
"BPF program executed {} instructions",
|
||||
vm.get_last_instruction_count()
|
||||
);
|
||||
} else if let Ok(instruction) = bincode::deserialize(tx_data) {
|
||||
if keyed_accounts[0].signer_key().is_none() {
|
||||
warn!("key[0] did not sign the transaction");
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
if let Ok(instruction) = bincode::deserialize(ix_data) {
|
||||
match instruction {
|
||||
LoaderInstruction::Write { offset, bytes } => {
|
||||
if keyed_accounts[0].signer_key().is_none() {
|
||||
warn!("key[0] did not sign the transaction");
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
let offset = offset as usize;
|
||||
let len = bytes.len();
|
||||
debug!("Write: offset={} length={}", offset, len);
|
||||
@ -140,15 +110,54 @@ pub fn process_instruction(
|
||||
keyed_accounts[0].account.data[offset..offset + len].copy_from_slice(&bytes);
|
||||
}
|
||||
LoaderInstruction::Finalize => {
|
||||
if keyed_accounts[0].signer_key().is_none() {
|
||||
warn!("key[0] did not sign the transaction");
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
keyed_accounts[0].account.executable = true;
|
||||
info!(
|
||||
"Finalize: account {:?}",
|
||||
keyed_accounts[0].signer_key().unwrap()
|
||||
);
|
||||
}
|
||||
LoaderInstruction::InvokeMain { data } => {
|
||||
if !keyed_accounts[0].account.executable {
|
||||
warn!("BPF account not executable");
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
let (progs, params) = keyed_accounts.split_at_mut(1);
|
||||
let prog = &progs[0].account.data;
|
||||
info!("Call BPF program");
|
||||
let (mut vm, heap_region) = match create_vm(prog) {
|
||||
Ok(info) => info,
|
||||
Err(e) => {
|
||||
warn!("Failed to create BPF VM: {}", e);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
};
|
||||
let mut v = serialize_parameters(program_id, params, &data);
|
||||
|
||||
match vm.execute_program(v.as_mut_slice(), &[], &[heap_region]) {
|
||||
Ok(status) => {
|
||||
if 0 == status {
|
||||
warn!("BPF program failed: {}", status);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("BPF VM failed to run program: {}", e);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
}
|
||||
deserialize_parameters(params, &v);
|
||||
info!(
|
||||
"BPF program executed {} instructions",
|
||||
vm.get_last_instruction_count()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Invalid program transaction: {:?}", tx_data);
|
||||
warn!("Invalid instruction data: {:?}", ix_data);
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
Ok(())
|
||||
|
Reference in New Issue
Block a user