diff --git a/programs/bpf/c/sdk/inc/solana_sdk.h b/programs/bpf/c/sdk/inc/solana_sdk.h index 08c2df139e..b3b4c0b721 100644 --- a/programs/bpf/c/sdk/inc/solana_sdk.h +++ b/programs/bpf/c/sdk/inc/solana_sdk.h @@ -194,6 +194,7 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) { */ typedef struct { uint64_t tick_height; /** Current ledger tick */ + const SolPubkey *program_id; /** program_id of the currently executing program */ } SolClusterInfo; /** @@ -269,6 +270,9 @@ SOL_FN_PREFIX bool sol_deserialize( if (cluster_info != NULL) { cluster_info->tick_height = *(uint64_t *) input; + input += sizeof(uint64_t); + cluster_info->program_id = (SolPubkey *) input; + input += sizeof(SolPubkey); } return true; } diff --git a/programs/bpf/c/src/noop++.cc b/programs/bpf/c/src/noop++.cc index c9f14a4bed..8b1de45af4 100644 --- a/programs/bpf/c/src/noop++.cc +++ b/programs/bpf/c/src/noop++.cc @@ -15,11 +15,16 @@ extern bool entrypoint(const uint8_t *input) { if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { return false; } + + sol_log("Tick height:"); sol_log_64(info.tick_height, 0, 0, 0, 0); + sol_log("Program identifier:"); + sol_log_key(info.program_id); // 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 // programs will have specific requirements so they can do their work. + sol_log("Account keys and instruction input data:"); sol_log_params(ka, ka_len, data, data_len); return true; } diff --git a/programs/bpf/c/src/noop.c b/programs/bpf/c/src/noop.c index f8aba98933..5b3f232e0e 100644 --- a/programs/bpf/c/src/noop.c +++ b/programs/bpf/c/src/noop.c @@ -16,11 +16,15 @@ extern bool entrypoint(const uint8_t *input) { if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { return false; } + sol_log("Tick height:"); sol_log_64(info.tick_height, 0, 0, 0, 0); + sol_log("Program identifier:"); + sol_log_key(info.program_id); // 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 // programs will have specific requirements so they can do their work. + sol_log("Account keys and instruction input data:"); sol_log_params(ka, ka_len, data, data_len); return true; } diff --git a/programs/native/bpf_loader/src/lib.rs b/programs/native/bpf_loader/src/lib.rs index ba0ec9c34a..1686446a3e 100644 --- a/programs/native/bpf_loader/src/lib.rs +++ b/programs/native/bpf_loader/src/lib.rs @@ -99,6 +99,7 @@ pub fn create_vm(prog: &[u8]) -> Result { } fn serialize_parameters( + program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], tick_height: u64, @@ -119,6 +120,7 @@ fn serialize_parameters( v.write_u64::(data.len() as u64).unwrap(); v.write_all(data).unwrap(); v.write_u64::(tick_height).unwrap(); + v.write_all(program_id.as_ref()).unwrap(); v } @@ -141,7 +143,12 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) { } solana_entrypoint!(entrypoint); -fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], tick_height: u64) -> bool { +fn entrypoint( + program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + tx_data: &[u8], + tick_height: u64, +) -> bool { static INIT: Once = ONCE_INIT; INIT.call_once(|| { // env_logger can only be initialized once @@ -159,7 +166,8 @@ fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], tick_height: return false; } }; - let mut v = serialize_parameters(&mut keyed_accounts[1..], &tx_data, tick_height); + let mut v = + serialize_parameters(program_id, &mut keyed_accounts[1..], &tx_data, tick_height); match vm.execute_program(v.as_mut_slice()) { Ok(status) => { if 0 == status { diff --git a/programs/native/erc20/src/lib.rs b/programs/native/erc20/src/lib.rs index 0af3812253..9dfb731d99 100644 --- a/programs/native/erc20/src/lib.rs +++ b/programs/native/erc20/src/lib.rs @@ -11,17 +11,23 @@ extern crate serde_derive; extern crate solana_sdk; use solana_sdk::account::KeyedAccount; +use solana_sdk::pubkey::Pubkey; use std::sync::{Once, ONCE_INIT}; mod token_program; solana_entrypoint!(entrypoint); -fn entrypoint(info: &mut [KeyedAccount], input: &[u8], _tick_height: u64) -> bool { +fn entrypoint( + program_id: &Pubkey, + info: &mut [KeyedAccount], + input: &[u8], + _tick_height: u64, +) -> bool { // env_logger can only be initialized once static INIT: Once = ONCE_INIT; INIT.call_once(env_logger::init); - match token_program::TokenProgram::process(info, input) { + match token_program::TokenProgram::process(program_id, info, input) { Err(err) => { error!("error: {:?}", err); false diff --git a/programs/native/erc20/src/token_program.rs b/programs/native/erc20/src/token_program.rs index fd7bb1ca39..bda87159b4 100644 --- a/programs/native/erc20/src/token_program.rs +++ b/programs/native/erc20/src/token_program.rs @@ -402,7 +402,7 @@ impl TokenProgram { Ok(()) } - pub fn process(info: &mut [KeyedAccount], input: &[u8]) -> Result<()> { + pub fn process(program_id: &Pubkey, info: &mut [KeyedAccount], input: &[u8]) -> Result<()> { let command = bincode::deserialize::(input).map_err(Self::map_to_invalid_args)?; info!("process_transaction: command={:?}", command); @@ -410,13 +410,7 @@ impl TokenProgram { .iter() .map(|keyed_account| { let account = &keyed_account.account; - - // - // TODO: Restore the following commented out block to valid program ids - // once https://github.com/solana-labs/solana/issues/1544 is fixed. - - /* - if account.program_id == info[0].account.program_id { + if account.owner == *program_id { match Self::deserialize(&account.userdata) { Ok(token_program) => token_program, Err(err) => { @@ -427,14 +421,6 @@ impl TokenProgram { } else { TokenProgram::Invalid } - */ - match Self::deserialize(&account.userdata) { - Ok(token_program) => token_program, - Err(err) => { - error!("deserialize failed: {:?}", err); - TokenProgram::Invalid - } - } }).collect(); for program_account in &input_program_accounts { diff --git a/programs/native/lua_loader/src/lib.rs b/programs/native/lua_loader/src/lib.rs index 19e1eea7b1..636571ae03 100644 --- a/programs/native/lua_loader/src/lib.rs +++ b/programs/native/lua_loader/src/lib.rs @@ -10,6 +10,7 @@ use bincode::deserialize; use rlua::{Lua, Result, Table}; use solana_sdk::account::KeyedAccount; use solana_sdk::loader_instruction::LoaderInstruction; +use solana_sdk::pubkey::Pubkey; use std::str; use std::sync::{Once, ONCE_INIT}; @@ -53,7 +54,12 @@ fn run_lua(keyed_accounts: &mut [KeyedAccount], code: &str, data: &[u8]) -> Resu } solana_entrypoint!(entrypoint); -fn entrypoint(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], _tick_height: u64) -> bool { +fn entrypoint( + _program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + tx_data: &[u8], + _tick_height: u64, +) -> bool { static INIT: Once = ONCE_INIT; INIT.call_once(|| { // env_logger can only be initialized once @@ -174,11 +180,11 @@ mod tests { (bob_pubkey, Account::new(1, 0, owner)), ]; let data = serialize(&10u64).unwrap(); - process(&mut create_keyed_accounts(&mut accounts), &data, 0); + process(&owner, &mut create_keyed_accounts(&mut accounts), &data, 0); assert_eq!(accounts[1].1.tokens, 90); assert_eq!(accounts[2].1.tokens, 11); - process(&mut create_keyed_accounts(&mut accounts), &data, 0); + process(&owner, &mut create_keyed_accounts(&mut accounts), &data, 0); assert_eq!(accounts[1].1.tokens, 80); assert_eq!(accounts[2].1.tokens, 21); } @@ -222,7 +228,7 @@ mod tests { (Pubkey::default(), Account::new(1, 0, owner)), ]; let mut keyed_accounts = create_keyed_accounts(&mut accounts); - process(&mut keyed_accounts, &[], 0); + process(&owner, &mut keyed_accounts, &[], 0); // Verify deterministic ordering of a serialized Lua table. assert_eq!( str::from_utf8(&keyed_accounts[3].account.userdata).unwrap(), @@ -281,19 +287,19 @@ mod tests { ).as_bytes() .to_vec(); - process(&mut keyed_accounts, &data, 0); + process(&owner, &mut keyed_accounts, &data, 0); assert_eq!(keyed_accounts[4].account.tokens, 1); let data = format!(r#""{}""#, carol_pubkey).into_bytes(); - process(&mut keyed_accounts, &data, 0); + process(&owner, &mut keyed_accounts, &data, 0); assert_eq!(keyed_accounts[4].account.tokens, 1); let data = format!(r#""{}""#, dan_pubkey).into_bytes(); - process(&mut keyed_accounts, &data, 0); + process(&owner, &mut keyed_accounts, &data, 0); assert_eq!(keyed_accounts[4].account.tokens, 101); // Pay day! let data = format!(r#""{}""#, erin_pubkey).into_bytes(); - process(&mut keyed_accounts, &data, 0); + process(&owner, &mut keyed_accounts, &data, 0); assert_eq!(keyed_accounts[4].account.tokens, 101); // No change! } } diff --git a/programs/native/noop/src/lib.rs b/programs/native/noop/src/lib.rs index 74dd356c80..af70664749 100644 --- a/programs/native/noop/src/lib.rs +++ b/programs/native/noop/src/lib.rs @@ -2,9 +2,16 @@ extern crate solana_sdk; use solana_sdk::account::KeyedAccount; +use solana_sdk::pubkey::Pubkey; solana_entrypoint!(entrypoint); -fn entrypoint(keyed_accounts: &mut [KeyedAccount], data: &[u8], tick_height: u64) -> bool { +fn entrypoint( + program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + tick_height: u64, +) -> bool { + println!("noop: program_id: {:?}", program_id); println!("noop: keyed_accounts: {:#?}", keyed_accounts); println!("noop: data: {:?}", data); println!("noop: tick_height: {:?}", tick_height); diff --git a/sdk/src/native_program.rs b/sdk/src/native_program.rs index fa5265e8db..03b7ea9ab1 100644 --- a/sdk/src/native_program.rs +++ b/sdk/src/native_program.rs @@ -1,12 +1,16 @@ use account::KeyedAccount; +use pubkey::Pubkey; // All native programs export a symbol named process() pub const ENTRYPOINT: &str = "process"; // Native program ENTRYPOINT prototype -pub type Entrypoint = - unsafe extern "C" fn(keyed_accounts: &mut [KeyedAccount], data: &[u8], tick_height: u64) - -> bool; +pub type Entrypoint = unsafe extern "C" fn( + program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + tick_height: u64, +) -> bool; // Convenience macro to define the native program entrypoint. Supply a fn to this macro that // conforms to the `Entrypoint` type signature. @@ -14,8 +18,13 @@ pub type Entrypoint = macro_rules! solana_entrypoint( ($entrypoint:ident) => ( #[no_mangle] - pub extern "C" fn process(keyed_accounts: &mut [KeyedAccount], data: &[u8], tick_height: u64) -> bool { - return $entrypoint(keyed_accounts, data, tick_height); + pub extern "C" fn process( + program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + tick_height: u64 + ) -> bool { + return $entrypoint(program_id, keyed_accounts, data, tick_height); } ) ); diff --git a/src/bank.rs b/src/bank.rs index f2e16d03ec..bd95935f39 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -854,6 +854,7 @@ impl Bank { keyed_accounts.append(&mut keyed_accounts2); if !native_loader::process_instruction( + &program_id, &mut keyed_accounts, &tx.instructions[instruction_index].userdata, self.tick_height(), diff --git a/src/native_loader.rs b/src/native_loader.rs index c5e0262289..27885990e8 100644 --- a/src/native_loader.rs +++ b/src/native_loader.rs @@ -54,6 +54,7 @@ pub fn id() -> Pubkey { } pub fn process_instruction( + program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], ix_userdata: &[u8], tick_height: u64, @@ -85,7 +86,12 @@ pub fn process_instruction( return false; } }; - return entrypoint(&mut keyed_accounts[1..], ix_userdata, tick_height); + return entrypoint( + program_id, + &mut keyed_accounts[1..], + ix_userdata, + tick_height, + ); }, Err(e) => { warn!("Unable to load: {:?}", e);