Replaces MockInvokeContext by ThisInvokeContext in tests (#20881)
* Replaces MockInvokeContext by ThisInvokeContext in BpfLoader, SystemInstructionProcessor, CLIs, ConfigProcessor, StakeProcessor and VoteProcessor. * Finally, removes MockInvokeContext, MockComputeMeter and MockLogger. * Adjusts assert_instruction_count test. * Moves ThisInvokeContext to the program-runtime crate.
This commit is contained in:
parent
0597594943
commit
7200c5106e
|
@ -3598,6 +3598,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"solana-bpf-loader-program",
|
"solana-bpf-loader-program",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana_rbpf",
|
"solana_rbpf",
|
||||||
"time 0.3.4",
|
"time 0.3.4",
|
||||||
|
@ -4563,6 +4564,7 @@ dependencies = [
|
||||||
"solana-config-program",
|
"solana-config-program",
|
||||||
"solana-faucet",
|
"solana-faucet",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-remote-wallet",
|
"solana-remote-wallet",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana-streamer",
|
"solana-streamer",
|
||||||
|
@ -4684,6 +4686,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5399,6 +5402,7 @@ dependencies = [
|
||||||
name = "solana-program-runtime"
|
name = "solana-program-runtime"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"log 0.4.14",
|
"log 0.4.14",
|
||||||
|
@ -5752,6 +5756,7 @@ dependencies = [
|
||||||
"solana-frozen-abi-macro 1.9.0",
|
"solana-frozen-abi-macro 1.9.0",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
"solana-metrics",
|
"solana-metrics",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana-vote-program",
|
"solana-vote-program",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -6022,6 +6027,7 @@ dependencies = [
|
||||||
"solana-frozen-abi-macro 1.9.0",
|
"solana-frozen-abi-macro 1.9.0",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
"solana-metrics",
|
"solana-metrics",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
|
@ -35,6 +35,7 @@ solana-client = { path = "../client", version = "=1.9.0" }
|
||||||
solana-config-program = { path = "../programs/config", version = "=1.9.0" }
|
solana-config-program = { path = "../programs/config", version = "=1.9.0" }
|
||||||
solana-faucet = { path = "../faucet", version = "=1.9.0" }
|
solana-faucet = { path = "../faucet", version = "=1.9.0" }
|
||||||
solana-logger = { path = "../logger", version = "=1.9.0" }
|
solana-logger = { path = "../logger", version = "=1.9.0" }
|
||||||
|
solana-program-runtime = { path = "../program-runtime", version = "=1.9.0" }
|
||||||
solana_rbpf = "=0.2.14"
|
solana_rbpf = "=0.2.14"
|
||||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.9.0" }
|
solana-remote-wallet = { path = "../remote-wallet", version = "=1.9.0" }
|
||||||
solana-sdk = { path = "../sdk", version = "=1.9.0" }
|
solana-sdk = { path = "../sdk", version = "=1.9.0" }
|
||||||
|
|
|
@ -24,6 +24,7 @@ use solana_client::{
|
||||||
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
||||||
tpu_client::{TpuClient, TpuClientConfig},
|
tpu_client::{TpuClient, TpuClientConfig},
|
||||||
};
|
};
|
||||||
|
use solana_program_runtime::invoke_context::ThisInvokeContext;
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
verifier,
|
verifier,
|
||||||
vm::{Config, Executable},
|
vm::{Config, Executable},
|
||||||
|
@ -40,7 +41,6 @@ use solana_sdk::{
|
||||||
message::Message,
|
message::Message,
|
||||||
native_token::Sol,
|
native_token::Sol,
|
||||||
packet::PACKET_DATA_SIZE,
|
packet::PACKET_DATA_SIZE,
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer},
|
signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer},
|
||||||
system_instruction::{self, SystemError},
|
system_instruction::{self, SystemError},
|
||||||
|
@ -1994,7 +1994,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
||||||
let mut program_data = Vec::new();
|
let mut program_data = Vec::new();
|
||||||
file.read_to_end(&mut program_data)
|
file.read_to_end(&mut program_data)
|
||||||
.map_err(|err| format!("Unable to read program file: {}", err))?;
|
.map_err(|err| format!("Unable to read program file: {}", err))?;
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
let mut invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
|
|
||||||
// Verify the program
|
// Verify the program
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl CostUpdateService {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_program_runtime::ProgramTiming;
|
use solana_program_runtime::instruction_processor::ProgramTiming;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -10,6 +10,7 @@ documentation = "https://docs.rs/solana-program-runtime"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bincode = "1.3.3"
|
||||||
libc = "0.2.101"
|
libc = "0.2.101"
|
||||||
libloading = "0.7.0"
|
libloading = "0.7.0"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use log::*;
|
use log::*;
|
||||||
use solana_program_runtime::{ExecuteDetailsTimings, PreAccount};
|
use solana_program_runtime::instruction_processor::{ExecuteDetailsTimings, PreAccount};
|
||||||
use solana_sdk::{account::AccountSharedData, pubkey, rent::Rent};
|
use solana_sdk::{account::AccountSharedData, pubkey, rent::Rent};
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
||||||
#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(min_specialization))]
|
#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(min_specialization))]
|
||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)] // TODO: Remove
|
||||||
|
|
||||||
mod instruction_processor;
|
pub mod instruction_processor;
|
||||||
mod native_loader;
|
pub mod instruction_recorder;
|
||||||
|
pub mod invoke_context;
|
||||||
pub use instruction_processor::*;
|
pub mod log_collector;
|
||||||
pub use native_loader::*;
|
pub mod native_loader;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use {
|
||||||
log::*,
|
log::*,
|
||||||
solana_banks_client::start_client,
|
solana_banks_client::start_client,
|
||||||
solana_banks_server::banks_server::start_local_server,
|
solana_banks_server::banks_server::start_local_server,
|
||||||
solana_program_runtime::InstructionProcessor,
|
solana_program_runtime::instruction_processor::InstructionProcessor,
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
bank::{Bank, ExecuteTimings},
|
bank::{Bank, ExecuteTimings},
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
|
@ -33,7 +33,7 @@ use {
|
||||||
message::Message,
|
message::Message,
|
||||||
native_token::sol_to_lamports,
|
native_token::sol_to_lamports,
|
||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
process_instruction::{self, stable_log, InvokeContext, ProcessInstructionWithContext},
|
process_instruction::{stable_log, InvokeContext, ProcessInstructionWithContext},
|
||||||
program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR},
|
program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -215,7 +215,7 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
|
||||||
panic!("Exceeded compute budget");
|
panic!("Exceeded compute budget");
|
||||||
}
|
}
|
||||||
|
|
||||||
match process_instruction::get_sysvar::<T>(invoke_context, id) {
|
match solana_program_runtime::invoke_context::get_sysvar::<T>(invoke_context, id) {
|
||||||
Ok(sysvar_data) => unsafe {
|
Ok(sysvar_data) => unsafe {
|
||||||
*(var_addr as *mut _ as *mut T) = sysvar_data;
|
*(var_addr as *mut _ as *mut T) = sysvar_data;
|
||||||
SUCCESS
|
SUCCESS
|
||||||
|
|
|
@ -2566,6 +2566,7 @@ dependencies = [
|
||||||
"solana-cli-output",
|
"solana-cli-output",
|
||||||
"solana-logger 1.9.0",
|
"solana-logger 1.9.0",
|
||||||
"solana-measure",
|
"solana-measure",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-runtime",
|
"solana-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana-transaction-status",
|
"solana-transaction-status",
|
||||||
|
@ -3230,6 +3231,7 @@ dependencies = [
|
||||||
name = "solana-program-runtime"
|
name = "solana-program-runtime"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"log",
|
"log",
|
||||||
|
@ -3438,6 +3440,7 @@ dependencies = [
|
||||||
"solana-frozen-abi 1.9.0",
|
"solana-frozen-abi 1.9.0",
|
||||||
"solana-frozen-abi-macro 1.9.0",
|
"solana-frozen-abi-macro 1.9.0",
|
||||||
"solana-metrics",
|
"solana-metrics",
|
||||||
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana-vote-program",
|
"solana-vote-program",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
|
@ -35,6 +35,7 @@ solana-logger = { path = "../../logger", version = "=1.9.0" }
|
||||||
solana-measure = { path = "../../measure", version = "=1.9.0" }
|
solana-measure = { path = "../../measure", version = "=1.9.0" }
|
||||||
solana_rbpf = "=0.2.14"
|
solana_rbpf = "=0.2.14"
|
||||||
solana-runtime = { path = "../../runtime", version = "=1.9.0" }
|
solana-runtime = { path = "../../runtime", version = "=1.9.0" }
|
||||||
|
solana-program-runtime = { path = "../../program-runtime", version = "=1.9.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
||||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.9.0" }
|
solana-transaction-status = { path = "../../transaction-status", version = "=1.9.0" }
|
||||||
solana-account-decoder = { path = "../../account-decoder", version = "=1.9.0" }
|
solana-account-decoder = { path = "../../account-decoder", version = "=1.9.0" }
|
||||||
|
|
|
@ -18,18 +18,18 @@ use solana_runtime::{
|
||||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||||
loader_utils::load_program,
|
loader_utils::load_program,
|
||||||
};
|
};
|
||||||
|
use solana_program_runtime::invoke_context::with_mock_invoke_context;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::AccountSharedData,
|
|
||||||
bpf_loader,
|
bpf_loader,
|
||||||
client::SyncClient,
|
client::SyncClient,
|
||||||
entrypoint::SUCCESS,
|
entrypoint::SUCCESS,
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
message::Message,
|
message::Message,
|
||||||
process_instruction::{InvokeContext, MockComputeMeter, MockInvokeContext},
|
process_instruction::InvokeContext,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, env, fs::File, io::Read, mem, path::PathBuf, rc::Rc, sync::Arc};
|
use std::{env, fs::File, io::Read, mem, path::PathBuf, sync::Arc};
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
/// BPF program file extension
|
/// BPF program file extension
|
||||||
|
@ -94,35 +94,14 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
.write_u64::<LittleEndian>(ARMSTRONG_LIMIT)
|
.write_u64::<LittleEndian>(ARMSTRONG_LIMIT)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
inner_iter.write_u64::<LittleEndian>(0).unwrap();
|
inner_iter.write_u64::<LittleEndian>(0).unwrap();
|
||||||
|
|
||||||
let loader_id = bpf_loader::id();
|
|
||||||
let program_id = solana_sdk::pubkey::new_rand();
|
|
||||||
let accounts = [
|
|
||||||
(
|
|
||||||
program_id,
|
|
||||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
solana_sdk::pubkey::new_rand(),
|
|
||||||
RefCell::new(AccountSharedData::new(
|
|
||||||
1,
|
|
||||||
10000001,
|
|
||||||
&solana_sdk::pubkey::new_rand(),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
let keyed_accounts: Vec<_> = accounts
|
|
||||||
.iter()
|
|
||||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
|
||||||
.collect();
|
|
||||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
|
||||||
|
|
||||||
let elf = load_elf("bench_alu").unwrap();
|
let elf = load_elf("bench_alu").unwrap();
|
||||||
|
let loader_id = bpf_loader::id();
|
||||||
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(&mut invoke_context).unwrap(),
|
register_syscalls(invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
|
@ -132,7 +111,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
&loader_id,
|
&loader_id,
|
||||||
executable.as_ref(),
|
executable.as_ref(),
|
||||||
&mut inner_iter,
|
&mut inner_iter,
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -181,6 +160,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
||||||
println!(" {:?} MIPS", mips);
|
println!(" {:?} MIPS", mips);
|
||||||
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
@ -220,41 +200,32 @@ fn bench_program_execute_noop(bencher: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_create_vm(bencher: &mut Bencher) {
|
fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
const BUDGET: u64 = 200_000;
|
let elf = load_elf("noop").unwrap();
|
||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
let accounts = [RefCell::new(AccountSharedData::new(
|
const BUDGET: u64 = 200_000;
|
||||||
1,
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
10000001,
|
{
|
||||||
&solana_sdk::pubkey::new_rand(),
|
let mut compute_meter = compute_meter.borrow_mut();
|
||||||
))];
|
let to_consume = compute_meter.get_remaining() - BUDGET;
|
||||||
let keys = [solana_sdk::pubkey::new_rand()];
|
compute_meter.consume(to_consume).unwrap();
|
||||||
let keyed_accounts: Vec<_> = keys
|
}
|
||||||
.iter()
|
|
||||||
.zip(&accounts)
|
|
||||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
|
||||||
.collect();
|
|
||||||
let instruction_data = vec![0u8];
|
|
||||||
|
|
||||||
let mut invoke_context = MockInvokeContext::new(&loader_id, keyed_accounts);
|
|
||||||
invoke_context.compute_meter = Rc::new(RefCell::new(MockComputeMeter { remaining: BUDGET }));
|
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
let (mut serialized, account_lengths) = serialize_parameters(
|
let (mut serialized, account_lengths) = serialize_parameters(
|
||||||
&loader_id,
|
&keyed_accounts[0].unsigned_key(),
|
||||||
&solana_sdk::pubkey::new_rand(),
|
&keyed_accounts[1].unsigned_key(),
|
||||||
keyed_accounts,
|
&keyed_accounts[2..],
|
||||||
&instruction_data,
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let elf = load_elf("noop").unwrap();
|
|
||||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(&mut invoke_context).unwrap(),
|
register_syscalls(invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -263,65 +234,50 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
&loader_id,
|
&loader_id,
|
||||||
executable.as_ref(),
|
executable.as_ref(),
|
||||||
serialized.as_slice_mut(),
|
serialized.as_slice_mut(),
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
const BUDGET: u64 = 200_000;
|
let elf = load_elf("tuner").unwrap();
|
||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
let program_id = solana_sdk::pubkey::new_rand();
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
|
const BUDGET: u64 = 200_000;
|
||||||
let accounts = [
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
(
|
{
|
||||||
program_id,
|
let mut compute_meter = compute_meter.borrow_mut();
|
||||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
let to_consume = compute_meter.get_remaining() - BUDGET;
|
||||||
),
|
compute_meter.consume(to_consume).unwrap();
|
||||||
(
|
}
|
||||||
solana_sdk::pubkey::new_rand(),
|
|
||||||
RefCell::new(AccountSharedData::new(
|
|
||||||
1,
|
|
||||||
10000001,
|
|
||||||
&solana_sdk::pubkey::new_rand(),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
let keyed_accounts: Vec<_> = accounts
|
|
||||||
.iter()
|
|
||||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
|
||||||
.collect();
|
|
||||||
let instruction_data = vec![0u8];
|
|
||||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
|
||||||
invoke_context.compute_meter = Rc::new(RefCell::new(MockComputeMeter { remaining: BUDGET }));
|
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
let (mut serialized, account_lengths) = serialize_parameters(
|
let (mut serialized, account_lengths) = serialize_parameters(
|
||||||
&loader_id,
|
&keyed_accounts[0].unsigned_key(),
|
||||||
&program_id,
|
&keyed_accounts[1].unsigned_key(),
|
||||||
&invoke_context.get_keyed_accounts().unwrap()[1..],
|
&keyed_accounts[2..],
|
||||||
&instruction_data,
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let elf = load_elf("tuner").unwrap();
|
|
||||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(&mut invoke_context).unwrap(),
|
register_syscalls(invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&loader_id,
|
&loader_id,
|
||||||
executable.as_ref(),
|
executable.as_ref(),
|
||||||
serialized.as_slice_mut(),
|
serialized.as_slice_mut(),
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -341,4 +297,5 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
measure.as_us(),
|
measure.as_us(),
|
||||||
vm.get_total_instruction_count(),
|
vm.get_total_instruction_count(),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ use solana_runtime::{
|
||||||
upgrade_program,
|
upgrade_program,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use solana_program_runtime::invoke_context::with_mock_invoke_context;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{AccountSharedData, ReadableAccount},
|
account::{AccountSharedData, ReadableAccount},
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
|
@ -40,10 +41,9 @@ use solana_sdk::{
|
||||||
compute_budget::{ComputeBudget, ComputeBudgetInstruction},
|
compute_budget::{ComputeBudget, ComputeBudgetInstruction},
|
||||||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||||
keyed_account::KeyedAccount,
|
|
||||||
loader_instruction,
|
loader_instruction,
|
||||||
message::{Message, SanitizedMessage},
|
message::{Message, SanitizedMessage},
|
||||||
process_instruction::{InvokeContext, MockInvokeContext},
|
process_instruction::InvokeContext,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{keypair_from_seed, Keypair, Signer},
|
signature::{keypair_from_seed, Keypair, Signer},
|
||||||
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
||||||
|
@ -56,8 +56,8 @@ use solana_transaction_status::{
|
||||||
TransactionStatusMeta, TransactionWithStatusMeta, UiTransactionEncoding,
|
TransactionStatusMeta, TransactionWithStatusMeta, UiTransactionEncoding,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell, collections::HashMap, convert::TryFrom, env, fs::File, io::Read, path::PathBuf,
|
collections::HashMap, convert::TryFrom, env, fs::File, io::Read, path::PathBuf, str::FromStr,
|
||||||
str::FromStr, sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// BPF program file extension
|
/// BPF program file extension
|
||||||
|
@ -190,28 +190,23 @@ fn upgrade_bpf_program(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_program(
|
fn run_program(name: &str) -> u64 {
|
||||||
name: &str,
|
|
||||||
loader_id: &Pubkey,
|
|
||||||
program_id: &Pubkey,
|
|
||||||
parameter_accounts: Vec<KeyedAccount>,
|
|
||||||
instruction_data: &[u8],
|
|
||||||
) -> Result<u64, InstructionError> {
|
|
||||||
let mut file = File::open(create_bpf_path(name)).unwrap();
|
let mut file = File::open(create_bpf_path(name)).unwrap();
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
file.read_to_end(&mut data).unwrap();
|
file.read_to_end(&mut data).unwrap();
|
||||||
|
let loader_id = bpf_loader::id();
|
||||||
let mut invoke_context = MockInvokeContext::new(&program_id, parameter_accounts);
|
with_mock_invoke_context(loader_id, 0, |invoke_context| {
|
||||||
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
let (parameter_bytes, account_lengths) = serialize_parameters(
|
let (parameter_bytes, account_lengths) = serialize_parameters(
|
||||||
&loader_id,
|
&keyed_accounts[0].unsigned_key(),
|
||||||
program_id,
|
&keyed_accounts[1].unsigned_key(),
|
||||||
&invoke_context.get_keyed_accounts().unwrap()[1..],
|
&keyed_accounts[2..],
|
||||||
&instruction_data,
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
|
|
||||||
let config = Config {
|
let config = Config {
|
||||||
enable_instruction_tracing: true,
|
enable_instruction_tracing: true,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
|
@ -220,7 +215,7 @@ fn run_program(
|
||||||
&data,
|
&data,
|
||||||
None,
|
None,
|
||||||
config,
|
config,
|
||||||
register_syscalls(&mut invoke_context).unwrap(),
|
register_syscalls(invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
|
@ -228,15 +223,14 @@ fn run_program(
|
||||||
let mut instruction_count = 0;
|
let mut instruction_count = 0;
|
||||||
let mut tracer = None;
|
let mut tracer = None;
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
|
invoke_context.set_return_data(Vec::new()).unwrap();
|
||||||
let mut parameter_bytes = parameter_bytes.clone();
|
let mut parameter_bytes = parameter_bytes.clone();
|
||||||
{
|
{
|
||||||
invoke_context.set_return_data(Vec::new()).unwrap();
|
|
||||||
|
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&loader_id,
|
&loader_id,
|
||||||
executable.as_ref(),
|
executable.as_ref(),
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -281,18 +275,18 @@ fn run_program(
|
||||||
tracer = Some(vm.get_tracer().clone());
|
tracer = Some(vm.get_tracer().clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let parameter_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
deserialize_parameters(
|
deserialize_parameters(
|
||||||
&loader_id,
|
&loader_id,
|
||||||
parameter_accounts,
|
&keyed_accounts[2..],
|
||||||
parameter_bytes.as_slice(),
|
parameter_bytes.as_slice(),
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
instruction_count
|
||||||
Ok(instruction_count)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_transaction_and_record_inner(
|
fn process_transaction_and_record_inner(
|
||||||
|
@ -1377,8 +1371,8 @@ fn assert_instruction_count() {
|
||||||
("noop++", 5),
|
("noop++", 5),
|
||||||
("relative_call", 26),
|
("relative_call", 26),
|
||||||
("return_data", 980),
|
("return_data", 980),
|
||||||
("sanity", 1246),
|
("sanity", 1248),
|
||||||
("sanity++", 1250),
|
("sanity++", 1252),
|
||||||
("secp256k1_recover", 25383),
|
("secp256k1_recover", 25383),
|
||||||
("sha", 1328),
|
("sha", 1328),
|
||||||
("struct_pass", 108),
|
("struct_pass", 108),
|
||||||
|
@ -1390,17 +1384,17 @@ fn assert_instruction_count() {
|
||||||
programs.extend_from_slice(&[
|
programs.extend_from_slice(&[
|
||||||
("solana_bpf_rust_128bit", 584),
|
("solana_bpf_rust_128bit", 584),
|
||||||
("solana_bpf_rust_alloc", 7388),
|
("solana_bpf_rust_alloc", 7388),
|
||||||
("solana_bpf_rust_custom_heap", 535),
|
("solana_bpf_rust_custom_heap", 536),
|
||||||
("solana_bpf_rust_dep_crate", 47),
|
("solana_bpf_rust_dep_crate", 47),
|
||||||
("solana_bpf_rust_external_spend", 506),
|
("solana_bpf_rust_external_spend", 507),
|
||||||
("solana_bpf_rust_iter", 824),
|
("solana_bpf_rust_iter", 824),
|
||||||
("solana_bpf_rust_many_args", 941),
|
("solana_bpf_rust_many_args", 941),
|
||||||
("solana_bpf_rust_mem", 3085),
|
("solana_bpf_rust_mem", 3086),
|
||||||
("solana_bpf_rust_membuiltins", 3976),
|
("solana_bpf_rust_membuiltins", 3976),
|
||||||
("solana_bpf_rust_noop", 480),
|
("solana_bpf_rust_noop", 481),
|
||||||
("solana_bpf_rust_param_passing", 146),
|
("solana_bpf_rust_param_passing", 146),
|
||||||
("solana_bpf_rust_rand", 487),
|
("solana_bpf_rust_rand", 488),
|
||||||
("solana_bpf_rust_sanity", 8454),
|
("solana_bpf_rust_sanity", 8455),
|
||||||
("solana_bpf_rust_secp256k1_recover", 25216),
|
("solana_bpf_rust_secp256k1_recover", 25216),
|
||||||
("solana_bpf_rust_sha", 30692),
|
("solana_bpf_rust_sha", 30692),
|
||||||
]);
|
]);
|
||||||
|
@ -1409,17 +1403,7 @@ fn assert_instruction_count() {
|
||||||
let mut passed = true;
|
let mut passed = true;
|
||||||
println!("\n {:36} expected actual diff", "BPF program");
|
println!("\n {:36} expected actual diff", "BPF program");
|
||||||
for program in programs.iter() {
|
for program in programs.iter() {
|
||||||
let loader_id = bpf_loader::id();
|
let count = run_program(program.0);
|
||||||
let program_id = Pubkey::new_unique();
|
|
||||||
let key = Pubkey::new_unique();
|
|
||||||
let mut program_account = RefCell::new(AccountSharedData::new(0, 0, &loader_id));
|
|
||||||
let mut account = RefCell::new(AccountSharedData::default());
|
|
||||||
let parameter_accounts = vec![
|
|
||||||
KeyedAccount::new(&program_id, false, &mut program_account),
|
|
||||||
KeyedAccount::new(&key, false, &mut account),
|
|
||||||
];
|
|
||||||
let count =
|
|
||||||
run_program(program.0, &loader_id, &program_id, parameter_accounts, &[]).unwrap();
|
|
||||||
let diff: i64 = count as i64 - program.1 as i64;
|
let diff: i64 = count as i64 - program.1 as i64;
|
||||||
println!(
|
println!(
|
||||||
" {:36} {:8} {:6} {:+5} ({:+3.0}%)",
|
" {:36} {:8} {:6} {:+5} ({:+3.0}%)",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
use crate::{alloc, BpfError};
|
use crate::{alloc, BpfError};
|
||||||
use alloc::Alloc;
|
use alloc::Alloc;
|
||||||
use solana_program_runtime::InstructionProcessor;
|
use solana_program_runtime::instruction_processor::InstructionProcessor;
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
aligned_memory::AlignedMemory,
|
aligned_memory::AlignedMemory,
|
||||||
ebpf,
|
ebpf,
|
||||||
|
@ -31,7 +31,7 @@ use solana_sdk::{
|
||||||
message::Message,
|
message::Message,
|
||||||
native_loader,
|
native_loader,
|
||||||
precompiles::is_precompile,
|
precompiles::is_precompile,
|
||||||
process_instruction::{self, stable_log, ComputeMeter, InvokeContext, Logger},
|
process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger},
|
||||||
program::MAX_RETURN_DATA,
|
program::MAX_RETURN_DATA,
|
||||||
pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN},
|
pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN},
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -982,7 +982,7 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId>(
|
||||||
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
|
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
|
||||||
let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?;
|
let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?;
|
||||||
|
|
||||||
*var = process_instruction::get_sysvar::<T>(*invoke_context, id)
|
*var = solana_program_runtime::invoke_context::get_sysvar::<T>(*invoke_context, id)
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
|
|
||||||
Ok(SUCCESS)
|
Ok(SUCCESS)
|
||||||
|
@ -2427,16 +2427,17 @@ impl<'a> SyscallObject<BpfError> for SyscallLogData<'a> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use solana_program_runtime::{
|
||||||
|
invoke_context::{ThisComputeMeter, ThisInvokeContext, ThisLogger},
|
||||||
|
log_collector::LogCollector,
|
||||||
|
};
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
|
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
bpf_loader,
|
bpf_loader, feature_set::FeatureSet, fee_calculator::FeeCalculator, hash::hashv,
|
||||||
fee_calculator::FeeCalculator,
|
|
||||||
hash::hashv,
|
|
||||||
process_instruction::{MockComputeMeter, MockInvokeContext, MockLogger},
|
|
||||||
};
|
};
|
||||||
use std::str::FromStr;
|
use std::{str::FromStr, sync::Arc};
|
||||||
|
|
||||||
macro_rules! assert_access_violation {
|
macro_rules! assert_access_violation {
|
||||||
($result:expr, $va:expr, $len:expr) => {
|
($result:expr, $va:expr, $len:expr) => {
|
||||||
|
@ -2762,10 +2763,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
let compute_meter = ThisComputeMeter::new_ref(string.len() as u64 - 1);
|
||||||
Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: string.len() as u64 - 1,
|
|
||||||
}));
|
|
||||||
let mut syscall_panic = SyscallPanic {
|
let mut syscall_panic = SyscallPanic {
|
||||||
compute_meter,
|
compute_meter,
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
|
@ -2787,10 +2785,7 @@ mod tests {
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
let compute_meter = ThisComputeMeter::new_ref(string.len() as u64);
|
||||||
Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: string.len() as u64,
|
|
||||||
}));
|
|
||||||
let mut syscall_panic = SyscallPanic {
|
let mut syscall_panic = SyscallPanic {
|
||||||
compute_meter,
|
compute_meter,
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
|
@ -2812,17 +2807,6 @@ mod tests {
|
||||||
fn test_syscall_sol_log() {
|
fn test_syscall_sol_log() {
|
||||||
let string = "Gaggablaghblagh!";
|
let string = "Gaggablaghblagh!";
|
||||||
let addr = string.as_ptr() as *const _ as u64;
|
let addr = string.as_ptr() as *const _ as u64;
|
||||||
|
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
|
||||||
Rc::new(RefCell::new(MockComputeMeter { remaining: 1000000 }));
|
|
||||||
let log = Rc::new(RefCell::new(vec![]));
|
|
||||||
let logger: Rc<RefCell<dyn Logger>> =
|
|
||||||
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
|
|
||||||
let mut syscall_sol_log = SyscallLog {
|
|
||||||
compute_meter,
|
|
||||||
logger,
|
|
||||||
loader_id: &bpf_loader::id(),
|
|
||||||
};
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![
|
vec![
|
||||||
|
@ -2838,7 +2822,14 @@ mod tests {
|
||||||
&config,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let log = Rc::new(LogCollector::default());
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut syscall_sol_log = SyscallLog {
|
||||||
|
compute_meter: ThisComputeMeter::new_ref(string.len() as u64),
|
||||||
|
logger: ThisLogger::new_ref(Some(log.clone())),
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_log.call(
|
syscall_sol_log.call(
|
||||||
0x100000000,
|
0x100000000,
|
||||||
|
@ -2850,9 +2841,20 @@ mod tests {
|
||||||
&mut result,
|
&mut result,
|
||||||
);
|
);
|
||||||
result.unwrap();
|
result.unwrap();
|
||||||
assert_eq!(log.borrow().len(), 1);
|
}
|
||||||
assert_eq!(log.borrow()[0], "Program log: Gaggablaghblagh!");
|
|
||||||
|
|
||||||
|
let log: Vec<String> = match Rc::try_unwrap(log) {
|
||||||
|
Ok(log) => log.into(),
|
||||||
|
Err(_) => panic!("Unwrap failed"),
|
||||||
|
};
|
||||||
|
assert_eq!(log.len(), 1);
|
||||||
|
assert_eq!(log[0], "Program log: Gaggablaghblagh!");
|
||||||
|
|
||||||
|
let mut syscall_sol_log = SyscallLog {
|
||||||
|
compute_meter: ThisComputeMeter::new_ref(string.len() as u64 * 3),
|
||||||
|
logger: ThisLogger::new_ref(None),
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_log.call(
|
syscall_sol_log.call(
|
||||||
0x100000001, // AccessViolation
|
0x100000001, // AccessViolation
|
||||||
|
@ -2886,14 +2888,9 @@ mod tests {
|
||||||
&mut result,
|
&mut result,
|
||||||
);
|
);
|
||||||
|
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
|
||||||
Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: (string.len() as u64 * 2) - 1,
|
|
||||||
}));
|
|
||||||
let logger: Rc<RefCell<dyn Logger>> = Rc::new(RefCell::new(MockLogger { log }));
|
|
||||||
let mut syscall_sol_log = SyscallLog {
|
let mut syscall_sol_log = SyscallLog {
|
||||||
compute_meter,
|
compute_meter: ThisComputeMeter::new_ref((string.len() as u64 * 2) - 1),
|
||||||
logger,
|
logger: ThisLogger::new_ref(None),
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
};
|
};
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
|
@ -2927,45 +2924,33 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_syscall_sol_log_u64() {
|
fn test_syscall_sol_log_u64() {
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
let log = Rc::new(LogCollector::default());
|
||||||
Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: std::u64::MAX,
|
{
|
||||||
}));
|
|
||||||
let log = Rc::new(RefCell::new(vec![]));
|
|
||||||
let logger: Rc<RefCell<dyn Logger>> =
|
|
||||||
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
|
|
||||||
let mut syscall_sol_log_u64 = SyscallLogU64 {
|
let mut syscall_sol_log_u64 = SyscallLogU64 {
|
||||||
cost: 0,
|
cost: 0,
|
||||||
compute_meter,
|
compute_meter: ThisComputeMeter::new_ref(std::u64::MAX),
|
||||||
logger,
|
logger: ThisLogger::new_ref(Some(log.clone())),
|
||||||
};
|
};
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(vec![], &config).unwrap();
|
let memory_mapping = MemoryMapping::new::<UserError>(vec![], &config).unwrap();
|
||||||
|
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result);
|
syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result);
|
||||||
result.unwrap();
|
result.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(log.borrow().len(), 1);
|
let log: Vec<String> = match Rc::try_unwrap(log) {
|
||||||
assert_eq!(log.borrow()[0], "Program log: 0x1, 0x2, 0x3, 0x4, 0x5");
|
Ok(log) => log.into(),
|
||||||
|
Err(_) => panic!("Unwrap failed"),
|
||||||
|
};
|
||||||
|
assert_eq!(log.len(), 1);
|
||||||
|
assert_eq!(log[0], "Program log: 0x1, 0x2, 0x3, 0x4, 0x5");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_syscall_sol_pubkey() {
|
fn test_syscall_sol_pubkey() {
|
||||||
let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
|
let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
|
||||||
let addr = &pubkey.as_ref()[0] as *const _ as u64;
|
let addr = &pubkey.as_ref()[0] as *const _ as u64;
|
||||||
|
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
|
||||||
Rc::new(RefCell::new(MockComputeMeter { remaining: 2 }));
|
|
||||||
let log = Rc::new(RefCell::new(vec![]));
|
|
||||||
let logger: Rc<RefCell<dyn Logger>> =
|
|
||||||
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
|
|
||||||
let mut syscall_sol_pubkey = SyscallLogPubkey {
|
|
||||||
cost: 1,
|
|
||||||
compute_meter,
|
|
||||||
logger,
|
|
||||||
loader_id: &bpf_loader::id(),
|
|
||||||
};
|
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![
|
vec![
|
||||||
|
@ -2981,15 +2966,36 @@ mod tests {
|
||||||
&config,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let log = Rc::new(LogCollector::default());
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut syscall_sol_pubkey = SyscallLogPubkey {
|
||||||
|
cost: 1,
|
||||||
|
compute_meter: ThisComputeMeter::new_ref(1),
|
||||||
|
logger: ThisLogger::new_ref(Some(log.clone())),
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_pubkey.call(0x100000000, 0, 0, 0, 0, &memory_mapping, &mut result);
|
syscall_sol_pubkey.call(0x100000000, 0, 0, 0, 0, &memory_mapping, &mut result);
|
||||||
result.unwrap();
|
result.unwrap();
|
||||||
assert_eq!(log.borrow().len(), 1);
|
}
|
||||||
|
|
||||||
|
let log: Vec<String> = match Rc::try_unwrap(log) {
|
||||||
|
Ok(log) => log.into(),
|
||||||
|
Err(_) => panic!("Unwrap failed"),
|
||||||
|
};
|
||||||
|
assert_eq!(log.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
log.borrow()[0],
|
log[0],
|
||||||
"Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN"
|
"Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut syscall_sol_pubkey = SyscallLogPubkey {
|
||||||
|
cost: 1,
|
||||||
|
compute_meter: ThisComputeMeter::new_ref(1),
|
||||||
|
logger: ThisLogger::new_ref(None),
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_pubkey.call(
|
syscall_sol_pubkey.call(
|
||||||
0x100000001, // AccessViolation
|
0x100000001, // AccessViolation
|
||||||
|
@ -3191,10 +3197,7 @@ mod tests {
|
||||||
&config,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
let compute_meter = ThisComputeMeter::new_ref((bytes1.len() + bytes2.len()) as u64);
|
||||||
Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: (bytes1.len() + bytes2.len()) as u64,
|
|
||||||
}));
|
|
||||||
let mut syscall = SyscallSha256 {
|
let mut syscall = SyscallSha256 {
|
||||||
sha256_base_cost: 0,
|
sha256_base_cost: 0,
|
||||||
sha256_byte_cost: 2,
|
sha256_byte_cost: 2,
|
||||||
|
@ -3281,11 +3284,15 @@ mod tests {
|
||||||
leader_schedule_epoch: 4,
|
leader_schedule_epoch: 4,
|
||||||
unix_timestamp: 5,
|
unix_timestamp: 5,
|
||||||
};
|
};
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_clock).unwrap();
|
bincode::serialize_into(&mut data, &src_clock).unwrap();
|
||||||
let sysvars = &[(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut syscall = SyscallGetClockSysvar {
|
let mut syscall = SyscallGetClockSysvar {
|
||||||
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
||||||
|
@ -3325,11 +3332,15 @@ mod tests {
|
||||||
first_normal_epoch: 3,
|
first_normal_epoch: 3,
|
||||||
first_normal_slot: 4,
|
first_normal_slot: 4,
|
||||||
};
|
};
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
|
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
|
||||||
let sysvars = &[(sysvar::epoch_schedule::id(), data)];
|
let sysvars = [(sysvar::epoch_schedule::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut syscall = SyscallGetEpochScheduleSysvar {
|
let mut syscall = SyscallGetEpochScheduleSysvar {
|
||||||
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
||||||
|
@ -3376,11 +3387,15 @@ mod tests {
|
||||||
lamports_per_signature: 1,
|
lamports_per_signature: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_fees).unwrap();
|
bincode::serialize_into(&mut data, &src_fees).unwrap();
|
||||||
let sysvars = &[(sysvar::fees::id(), data)];
|
let sysvars = [(sysvar::fees::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut syscall = SyscallGetFeesSysvar {
|
let mut syscall = SyscallGetFeesSysvar {
|
||||||
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
||||||
|
@ -3418,11 +3433,15 @@ mod tests {
|
||||||
exemption_threshold: 2.0,
|
exemption_threshold: 2.0,
|
||||||
burn_percent: 3,
|
burn_percent: 3,
|
||||||
};
|
};
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_rent).unwrap();
|
bincode::serialize_into(&mut data, &src_rent).unwrap();
|
||||||
let sysvars = &[(sysvar::rent::id(), data)];
|
let sysvars = [(sysvar::rent::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut syscall = SyscallGetRentSysvar {
|
let mut syscall = SyscallGetRentSysvar {
|
||||||
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
||||||
|
@ -3530,11 +3549,9 @@ mod tests {
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
remaining: u64,
|
remaining: u64,
|
||||||
) -> Result<Pubkey, EbpfError<BpfError>> {
|
) -> Result<Pubkey, EbpfError<BpfError>> {
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
|
||||||
Rc::new(RefCell::new(MockComputeMeter { remaining }));
|
|
||||||
let mut syscall = SyscallCreateProgramAddress {
|
let mut syscall = SyscallCreateProgramAddress {
|
||||||
cost: 1,
|
cost: 1,
|
||||||
compute_meter: compute_meter.clone(),
|
compute_meter: ThisComputeMeter::new_ref(remaining),
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
};
|
};
|
||||||
let (address, _) = call_program_address_common(seeds, program_id, &mut syscall)?;
|
let (address, _) = call_program_address_common(seeds, program_id, &mut syscall)?;
|
||||||
|
@ -3546,11 +3563,9 @@ mod tests {
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
remaining: u64,
|
remaining: u64,
|
||||||
) -> Result<(Pubkey, u8), EbpfError<BpfError>> {
|
) -> Result<(Pubkey, u8), EbpfError<BpfError>> {
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
|
||||||
Rc::new(RefCell::new(MockComputeMeter { remaining }));
|
|
||||||
let mut syscall = SyscallTryFindProgramAddress {
|
let mut syscall = SyscallTryFindProgramAddress {
|
||||||
cost: 1,
|
cost: 1,
|
||||||
compute_meter: compute_meter.clone(),
|
compute_meter: ThisComputeMeter::new_ref(remaining),
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
};
|
};
|
||||||
call_program_address_common(seeds, program_id, &mut syscall)
|
call_program_address_common(seeds, program_id, &mut syscall)
|
||||||
|
|
|
@ -18,6 +18,7 @@ solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
solana-logger = { path = "../../logger", version = "=1.9.0" }
|
solana-logger = { path = "../../logger", version = "=1.9.0" }
|
||||||
|
solana-program-runtime = { path = "../../program-runtime", version = "=1.9.0" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
|
|
@ -138,28 +138,25 @@ mod tests {
|
||||||
use crate::{config_instruction, get_config_data, id, ConfigKeys, ConfigState};
|
use crate::{config_instruction, get_config_data, id, ConfigKeys, ConfigState};
|
||||||
use bincode::serialized_size;
|
use bincode::serialized_size;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use solana_program_runtime::invoke_context::mock_process_instruction;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{Account, AccountSharedData},
|
account::AccountSharedData,
|
||||||
keyed_account::create_keyed_accounts_unified,
|
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
system_instruction::SystemInstruction,
|
system_instruction::SystemInstruction,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
fn process_instruction(
|
fn process_instruction(
|
||||||
owner: &Pubkey,
|
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
|
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
|
mock_process_instruction(
|
||||||
let mut keyed_accounts = keyed_accounts.to_vec();
|
&id(),
|
||||||
keyed_accounts.insert(0, (false, false, owner, &processor_account));
|
Vec::new(),
|
||||||
super::process_instruction(
|
|
||||||
1,
|
|
||||||
instruction_data,
|
instruction_data,
|
||||||
&mut MockInvokeContext::new(owner, create_keyed_accounts_unified(&keyed_accounts)),
|
keyed_accounts,
|
||||||
|
super::process_instruction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,8 +184,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_config_account(keys: Vec<(Pubkey, bool)>) -> (Keypair, RefCell<AccountSharedData>) {
|
fn create_config_account(
|
||||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
keys: Vec<(Pubkey, bool)>,
|
||||||
|
) -> (Keypair, Rc<RefCell<AccountSharedData>>) {
|
||||||
|
let from_pubkey = Pubkey::new_unique();
|
||||||
let config_keypair = Keypair::new();
|
let config_keypair = Keypair::new();
|
||||||
let config_pubkey = config_keypair.pubkey();
|
let config_pubkey = config_keypair.pubkey();
|
||||||
|
|
||||||
|
@ -204,14 +203,10 @@ mod tests {
|
||||||
} => space,
|
} => space,
|
||||||
_ => panic!("Not a CreateAccount system instruction"),
|
_ => panic!("Not a CreateAccount system instruction"),
|
||||||
};
|
};
|
||||||
let config_account = RefCell::new(AccountSharedData::from(Account {
|
let config_account = AccountSharedData::new_ref(0, space as usize, &id());
|
||||||
data: vec![0; space as usize],
|
let keyed_accounts = [(true, false, config_pubkey, config_account.clone())];
|
||||||
owner: id(),
|
|
||||||
..Account::default()
|
|
||||||
}));
|
|
||||||
let keyed_accounts = [(true, false, &config_pubkey, &config_account)];
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instructions[1].data, &keyed_accounts),
|
process_instruction(&instructions[1].data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -237,9 +232,9 @@ mod tests {
|
||||||
let my_config = MyConfig::new(42);
|
let my_config = MyConfig::new(42);
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
||||||
let keyed_accounts = [(true, false, &config_pubkey, &config_account)];
|
let keyed_accounts = [(true, false, config_pubkey, config_account.clone())];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -258,9 +253,9 @@ mod tests {
|
||||||
|
|
||||||
let mut instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
let mut instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
||||||
instruction.data = vec![0; 123]; // <-- Replace data with a vector that's too large
|
instruction.data = vec![0; 123]; // <-- Replace data with a vector that's too large
|
||||||
let keyed_accounts = [(true, false, &config_pubkey, &config_account)];
|
let keyed_accounts = [(true, false, config_pubkey, config_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::InvalidInstructionData)
|
Err(InstructionError::InvalidInstructionData)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -275,9 +270,9 @@ mod tests {
|
||||||
|
|
||||||
let mut instruction = config_instruction::store(&config_pubkey, true, vec![], &my_config);
|
let mut instruction = config_instruction::store(&config_pubkey, true, vec![], &my_config);
|
||||||
instruction.accounts[0].is_signer = false; // <----- not a signer
|
instruction.accounts[0].is_signer = false; // <----- not a signer
|
||||||
let keyed_accounts = [(false, false, &config_pubkey, &config_account)];
|
let keyed_accounts = [(false, false, config_pubkey, config_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -285,9 +280,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_store_with_additional_signers() {
|
fn test_process_store_with_additional_signers() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = Pubkey::new_unique();
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer1_pubkey = solana_sdk::pubkey::new_rand();
|
let signer1_pubkey = Pubkey::new_unique();
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(pubkey, false),
|
(pubkey, false),
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
|
@ -298,15 +293,15 @@ mod tests {
|
||||||
let my_config = MyConfig::new(42);
|
let my_config = MyConfig::new(42);
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let signer1_account = RefCell::new(AccountSharedData::default());
|
let signer1_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account.clone()),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
(true, false, &signer1_pubkey, &signer1_account),
|
(true, false, signer1_pubkey, signer1_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
||||||
|
@ -320,21 +315,18 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_store_without_config_signer() {
|
fn test_process_store_without_config_signer() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = Pubkey::new_unique();
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let keys = vec![(pubkey, false), (signer0_pubkey, true)];
|
let keys = vec![(pubkey, false), (signer0_pubkey, true)];
|
||||||
let (config_keypair, _) = create_config_account(keys.clone());
|
let (config_keypair, _) = create_config_account(keys.clone());
|
||||||
let config_pubkey = config_keypair.pubkey();
|
let config_pubkey = config_keypair.pubkey();
|
||||||
let my_config = MyConfig::new(42);
|
let my_config = MyConfig::new(42);
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
||||||
let signer0_account = RefCell::new(AccountSharedData::from(Account {
|
let signer0_account = AccountSharedData::new_ref(0, 0, &id());
|
||||||
owner: id(),
|
let keyed_accounts = [(true, false, signer0_pubkey, signer0_account)];
|
||||||
..Account::default()
|
|
||||||
}));
|
|
||||||
let keyed_accounts = [(true, false, &signer0_pubkey, &signer0_account)];
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::InvalidAccountData)
|
Err(InstructionError::InvalidAccountData)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -342,10 +334,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_store_with_bad_additional_signer() {
|
fn test_process_store_with_bad_additional_signer() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer1_pubkey = solana_sdk::pubkey::new_rand();
|
let signer1_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let signer1_account = RefCell::new(AccountSharedData::default());
|
let signer1_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keys = vec![(signer0_pubkey, true)];
|
let keys = vec![(signer0_pubkey, true)];
|
||||||
let (config_keypair, config_account) = create_config_account(keys.clone());
|
let (config_keypair, config_account) = create_config_account(keys.clone());
|
||||||
let config_pubkey = config_keypair.pubkey();
|
let config_pubkey = config_keypair.pubkey();
|
||||||
|
@ -355,18 +347,18 @@ mod tests {
|
||||||
|
|
||||||
// Config-data pubkey doesn't match signer
|
// Config-data pubkey doesn't match signer
|
||||||
let mut keyed_accounts = [
|
let mut keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account),
|
||||||
(true, false, &signer1_pubkey, &signer1_account),
|
(true, false, signer1_pubkey, signer1_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Config-data pubkey not a signer
|
// Config-data pubkey not a signer
|
||||||
keyed_accounts[1] = (false, false, &signer0_pubkey, &signer0_account);
|
keyed_accounts[1] = (false, false, signer0_pubkey, signer0_account);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -374,13 +366,13 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_updates() {
|
fn test_config_updates() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = Pubkey::new_unique();
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer1_pubkey = solana_sdk::pubkey::new_rand();
|
let signer1_pubkey = Pubkey::new_unique();
|
||||||
let signer2_pubkey = solana_sdk::pubkey::new_rand();
|
let signer2_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let signer1_account = RefCell::new(AccountSharedData::default());
|
let signer1_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let signer2_account = RefCell::new(AccountSharedData::default());
|
let signer2_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(pubkey, false),
|
(pubkey, false),
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
|
@ -392,12 +384,12 @@ mod tests {
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
||||||
let mut keyed_accounts = [
|
let mut keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account.clone()),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
(true, false, &signer1_pubkey, &signer1_account),
|
(true, false, signer1_pubkey, signer1_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -407,7 +399,7 @@ mod tests {
|
||||||
config_instruction::store(&config_pubkey, false, keys.clone(), &new_config);
|
config_instruction::store(&config_pubkey, false, keys.clone(), &new_config);
|
||||||
keyed_accounts[0].0 = false;
|
keyed_accounts[0].0 = false;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
||||||
|
@ -423,7 +415,7 @@ mod tests {
|
||||||
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
||||||
keyed_accounts[2].0 = false;
|
keyed_accounts[2].0 = false;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -434,9 +426,9 @@ mod tests {
|
||||||
(signer2_pubkey, true),
|
(signer2_pubkey, true),
|
||||||
];
|
];
|
||||||
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
|
||||||
keyed_accounts[2] = (true, false, &signer2_pubkey, &signer2_account);
|
keyed_accounts[2] = (true, false, signer2_pubkey, signer2_account);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -446,7 +438,7 @@ mod tests {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let config_address = Pubkey::new_unique();
|
let config_address = Pubkey::new_unique();
|
||||||
let signer0_pubkey = Pubkey::new_unique();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(config_address, false),
|
(config_address, false),
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
|
@ -459,12 +451,12 @@ mod tests {
|
||||||
// Attempt initialization with duplicate signer inputs
|
// Attempt initialization with duplicate signer inputs
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account.clone()),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::InvalidArgument),
|
Err(InstructionError::InvalidArgument),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -475,8 +467,8 @@ mod tests {
|
||||||
let config_address = Pubkey::new_unique();
|
let config_address = Pubkey::new_unique();
|
||||||
let signer0_pubkey = Pubkey::new_unique();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer1_pubkey = Pubkey::new_unique();
|
let signer1_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let signer1_account = RefCell::new(AccountSharedData::default());
|
let signer1_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(config_address, false),
|
(config_address, false),
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
|
@ -488,12 +480,12 @@ mod tests {
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
||||||
let mut keyed_accounts = [
|
let mut keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
(true, false, &signer1_pubkey, &signer1_account),
|
(true, false, signer1_pubkey, signer1_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -505,9 +497,9 @@ mod tests {
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
];
|
];
|
||||||
let instruction = config_instruction::store(&config_pubkey, false, dupe_keys, &new_config);
|
let instruction = config_instruction::store(&config_pubkey, false, dupe_keys, &new_config);
|
||||||
keyed_accounts[2] = keyed_accounts[1];
|
keyed_accounts[2] = keyed_accounts[1].clone();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::InvalidArgument),
|
Err(InstructionError::InvalidArgument),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -515,9 +507,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_updates_requiring_config() {
|
fn test_config_updates_requiring_config() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = Pubkey::new_unique();
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(pubkey, false),
|
(pubkey, false),
|
||||||
(signer0_pubkey, true),
|
(signer0_pubkey, true),
|
||||||
|
@ -535,11 +527,11 @@ mod tests {
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account.clone()),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -548,7 +540,7 @@ mod tests {
|
||||||
let instruction =
|
let instruction =
|
||||||
config_instruction::store(&config_pubkey, true, keys.clone(), &new_config);
|
config_instruction::store(&config_pubkey, true, keys.clone(), &new_config);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
let meta_data: ConfigKeys = deserialize(config_account.borrow().data()).unwrap();
|
||||||
|
@ -563,32 +555,32 @@ mod tests {
|
||||||
let keys = vec![(pubkey, false), (config_keypair.pubkey(), true)];
|
let keys = vec![(pubkey, false), (config_keypair.pubkey(), true)];
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts[0..1]),
|
process_instruction(&instruction.data, &keyed_accounts[0..1]),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_initialize_no_panic() {
|
fn test_config_initialize_no_panic() {
|
||||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
let from_pubkey = Pubkey::new_unique();
|
||||||
let config_pubkey = solana_sdk::pubkey::new_rand();
|
let config_pubkey = Pubkey::new_unique();
|
||||||
let (_, _config_account) = create_config_account(vec![]);
|
let (_, _config_account) = create_config_account(vec![]);
|
||||||
let instructions =
|
let instructions =
|
||||||
config_instruction::create_account::<MyConfig>(&from_pubkey, &config_pubkey, 1, vec![]);
|
config_instruction::create_account::<MyConfig>(&from_pubkey, &config_pubkey, 1, vec![]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instructions[1].data, &[]),
|
process_instruction(&instructions[1].data, &[]),
|
||||||
Err(InstructionError::NotEnoughAccountKeys)
|
Err(InstructionError::NotEnoughAccountKeys)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_config_bad_owner() {
|
fn test_config_bad_owner() {
|
||||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
let from_pubkey = Pubkey::new_unique();
|
||||||
let config_pubkey = solana_sdk::pubkey::new_rand();
|
let config_pubkey = Pubkey::new_unique();
|
||||||
let new_config = MyConfig::new(84);
|
let new_config = MyConfig::new(84);
|
||||||
let signer0_pubkey = solana_sdk::pubkey::new_rand();
|
let signer0_pubkey = Pubkey::new_unique();
|
||||||
let signer0_account = RefCell::new(AccountSharedData::default());
|
let signer0_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let config_account = RefCell::new(AccountSharedData::default());
|
let config_account = AccountSharedData::new_ref(0, 0, &Pubkey::new_unique());
|
||||||
let (_, _config_account) = create_config_account(vec![]);
|
let (_, _config_account) = create_config_account(vec![]);
|
||||||
let keys = vec![
|
let keys = vec![
|
||||||
(from_pubkey, false),
|
(from_pubkey, false),
|
||||||
|
@ -598,11 +590,11 @@ mod tests {
|
||||||
|
|
||||||
let instruction = config_instruction::store(&config_pubkey, true, keys, &new_config);
|
let instruction = config_instruction::store(&config_pubkey, true, keys, &new_config);
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(true, false, &config_pubkey, &config_account),
|
(true, false, config_pubkey, config_account),
|
||||||
(true, false, &signer0_pubkey, &signer0_account),
|
(true, false, signer0_pubkey, signer0_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&id(), &instruction.data, &keyed_accounts),
|
process_instruction(&instruction.data, &keyed_accounts),
|
||||||
Err(InstructionError::InvalidAccountOwner)
|
Err(InstructionError::InvalidAccountOwner)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ solana-frozen-abi = { path = "../../frozen-abi", version = "=1.9.0" }
|
||||||
solana-frozen-abi-macro = { path = "../../frozen-abi/macro", version = "=1.9.0" }
|
solana-frozen-abi-macro = { path = "../../frozen-abi/macro", version = "=1.9.0" }
|
||||||
solana-metrics = { path = "../../metrics", version = "=1.9.0" }
|
solana-metrics = { path = "../../metrics", version = "=1.9.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
||||||
|
solana-program-runtime = { path = "../../program-runtime", version = "=1.9.0" }
|
||||||
solana-vote-program = { path = "../vote", version = "=1.9.0" }
|
solana-vote-program = { path = "../vote", version = "=1.9.0" }
|
||||||
solana-config-program = { path = "../config", version = "=1.9.0" }
|
solana-config-program = { path = "../config", version = "=1.9.0" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use {
|
use {
|
||||||
crate::{config, stake_state::StakeAccount},
|
crate::{config, stake_state::StakeAccount},
|
||||||
log::*,
|
log::*,
|
||||||
|
solana_program_runtime::invoke_context::get_sysvar,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
feature_set,
|
feature_set,
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
keyed_account::{from_keyed_account, get_signers, keyed_account_at_index},
|
keyed_account::{from_keyed_account, get_signers, keyed_account_at_index},
|
||||||
process_instruction::{get_sysvar, InvokeContext},
|
process_instruction::InvokeContext,
|
||||||
program_utils::limited_deserialize,
|
program_utils::limited_deserialize,
|
||||||
stake::{
|
stake::{
|
||||||
instruction::StakeInstruction,
|
instruction::StakeInstruction,
|
||||||
|
@ -326,11 +327,13 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::stake_state::{Meta, StakeState};
|
use crate::stake_state::{Meta, StakeState};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
|
use solana_program_runtime::invoke_context::{
|
||||||
|
mock_process_instruction, prepare_mock_invoke_context, ThisInvokeContext,
|
||||||
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{self, Account, AccountSharedData, WritableAccount},
|
account::{self, AccountSharedData},
|
||||||
|
feature_set::FeatureSet,
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
keyed_account::create_keyed_accounts_unified,
|
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
stake::{
|
stake::{
|
||||||
|
@ -340,17 +343,14 @@ mod tests {
|
||||||
},
|
},
|
||||||
sysvar::{stake_history::StakeHistory, Sysvar},
|
sysvar::{stake_history::StakeHistory, Sysvar},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, str::FromStr};
|
use std::{cell::RefCell, rc::Rc, str::FromStr, sync::Arc};
|
||||||
|
|
||||||
fn create_default_account() -> RefCell<AccountSharedData> {
|
fn create_default_account() -> Rc<RefCell<AccountSharedData>> {
|
||||||
RefCell::new(AccountSharedData::default())
|
AccountSharedData::new_ref(0, 0, &Pubkey::new_unique())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_default_stake_account() -> RefCell<AccountSharedData> {
|
fn create_default_stake_account() -> Rc<RefCell<AccountSharedData>> {
|
||||||
RefCell::new(AccountSharedData::from(Account {
|
AccountSharedData::new_ref(0, 0, &id())
|
||||||
owner: id(),
|
|
||||||
..Account::default()
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_stake_state_pubkey() -> Pubkey {
|
fn invalid_stake_state_pubkey() -> Pubkey {
|
||||||
|
@ -370,35 +370,24 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_instruction(
|
fn process_instruction(
|
||||||
owner: &Pubkey,
|
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
|
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
|
mock_process_instruction(
|
||||||
let mut keyed_accounts = keyed_accounts.to_vec();
|
&id(),
|
||||||
keyed_accounts.insert(0, (false, false, owner, &processor_account));
|
Vec::new(),
|
||||||
super::process_instruction(
|
|
||||||
1,
|
|
||||||
instruction_data,
|
instruction_data,
|
||||||
&mut MockInvokeContext::new(owner, create_keyed_accounts_unified(&keyed_accounts)),
|
keyed_accounts,
|
||||||
|
super::process_instruction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_instruction_as_one_arg(instruction: &Instruction) -> Result<(), InstructionError> {
|
fn process_instruction_as_one_arg(instruction: &Instruction) -> Result<(), InstructionError> {
|
||||||
let processor_account = RefCell::new(AccountSharedData::from(Account {
|
let accounts = instruction.accounts.iter().map(|meta| {
|
||||||
owner: solana_sdk::native_loader::id(),
|
Rc::new(RefCell::new(if sysvar::clock::check_id(&meta.pubkey) {
|
||||||
..Account::default()
|
|
||||||
}));
|
|
||||||
let accounts: Vec<_> = instruction
|
|
||||||
.accounts
|
|
||||||
.iter()
|
|
||||||
.map(|meta| {
|
|
||||||
RefCell::new(if sysvar::clock::check_id(&meta.pubkey) {
|
|
||||||
account::create_account_shared_data_for_test(&sysvar::clock::Clock::default())
|
account::create_account_shared_data_for_test(&sysvar::clock::Clock::default())
|
||||||
} else if sysvar::rewards::check_id(&meta.pubkey) {
|
} else if sysvar::rewards::check_id(&meta.pubkey) {
|
||||||
account::create_account_shared_data_for_test(&sysvar::rewards::Rewards::new(
|
account::create_account_shared_data_for_test(&sysvar::rewards::Rewards::new(0.0))
|
||||||
0.0,
|
|
||||||
))
|
|
||||||
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
||||||
account::create_account_shared_data_for_test(&StakeHistory::default())
|
account::create_account_shared_data_for_test(&StakeHistory::default())
|
||||||
} else if stake_config::check_id(&meta.pubkey) {
|
} else if stake_config::check_id(&meta.pubkey) {
|
||||||
|
@ -406,55 +395,48 @@ mod tests {
|
||||||
} else if sysvar::rent::check_id(&meta.pubkey) {
|
} else if sysvar::rent::check_id(&meta.pubkey) {
|
||||||
account::create_account_shared_data_for_test(&Rent::default())
|
account::create_account_shared_data_for_test(&Rent::default())
|
||||||
} else if meta.pubkey == invalid_stake_state_pubkey() {
|
} else if meta.pubkey == invalid_stake_state_pubkey() {
|
||||||
AccountSharedData::from(Account {
|
AccountSharedData::new(0, 0, &id())
|
||||||
owner: id(),
|
|
||||||
..Account::default()
|
|
||||||
})
|
|
||||||
} else if meta.pubkey == invalid_vote_state_pubkey() {
|
} else if meta.pubkey == invalid_vote_state_pubkey() {
|
||||||
AccountSharedData::from(Account {
|
AccountSharedData::new(0, 0, &solana_vote_program::id())
|
||||||
owner: solana_vote_program::id(),
|
|
||||||
..Account::default()
|
|
||||||
})
|
|
||||||
} else if meta.pubkey == spoofed_stake_state_pubkey() {
|
} else if meta.pubkey == spoofed_stake_state_pubkey() {
|
||||||
AccountSharedData::from(Account {
|
AccountSharedData::new(0, 0, &spoofed_stake_program_id())
|
||||||
owner: spoofed_stake_program_id(),
|
|
||||||
..Account::default()
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
AccountSharedData::from(Account {
|
AccountSharedData::new(0, 0, &id())
|
||||||
owner: id(),
|
}))
|
||||||
..Account::default()
|
});
|
||||||
})
|
let keyed_accounts: Vec<_> = instruction
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut keyed_accounts: Vec<_> = instruction
|
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.zip(accounts.iter())
|
.zip(accounts)
|
||||||
.map(|(meta, account)| (meta.is_signer, false, &meta.pubkey, account))
|
.map(|(meta, account)| (meta.is_signer, meta.is_writable, meta.pubkey, account))
|
||||||
.collect();
|
.collect();
|
||||||
let processor_id = id();
|
let mut preparation = prepare_mock_invoke_context(&[], &instruction.data, &keyed_accounts);
|
||||||
keyed_accounts.insert(0, (false, false, &processor_id, &processor_account));
|
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
|
||||||
let mut invoke_context = MockInvokeContext::new(
|
let program_indices = vec![preparation.accounts.len()];
|
||||||
&processor_id,
|
preparation.accounts.push((id(), processor_account));
|
||||||
create_keyed_accounts_unified(&keyed_accounts),
|
|
||||||
);
|
|
||||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||||
let sysvars = &[(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&preparation.accounts,
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
invoke_context.push(
|
||||||
|
&preparation.message,
|
||||||
|
&preparation.message.instructions[0],
|
||||||
|
&program_indices,
|
||||||
|
Some(&preparation.account_indices),
|
||||||
|
)?;
|
||||||
super::process_instruction(1, &instruction.data, &mut invoke_context)
|
super::process_instruction(1, &instruction.data, &mut invoke_context)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stake_process_instruction() {
|
fn test_stake_process_instruction() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::initialize(
|
process_instruction_as_one_arg(&instruction::initialize(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Authorized::default(),
|
&Authorized::default(),
|
||||||
&Lockup::default()
|
&Lockup::default()
|
||||||
)),
|
)),
|
||||||
|
@ -462,9 +444,9 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::authorize(
|
process_instruction_as_one_arg(&instruction::authorize(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
StakeAuthorize::Staker,
|
StakeAuthorize::Staker,
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
|
@ -473,8 +455,8 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::split(
|
&instruction::split(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
&invalid_stake_state_pubkey(),
|
&invalid_stake_state_pubkey(),
|
||||||
)[2]
|
)[2]
|
||||||
|
@ -484,9 +466,9 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::merge(
|
&instruction::merge(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&invalid_stake_state_pubkey(),
|
&invalid_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)[0]
|
)[0]
|
||||||
),
|
),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
@ -494,11 +476,11 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::split_with_seed(
|
&instruction::split_with_seed(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
&invalid_stake_state_pubkey(),
|
&invalid_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
"seed"
|
"seed"
|
||||||
)[1]
|
)[1]
|
||||||
),
|
),
|
||||||
|
@ -506,17 +488,17 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::delegate_stake(
|
process_instruction_as_one_arg(&instruction::delegate_stake(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&invalid_vote_state_pubkey(),
|
&invalid_vote_state_pubkey(),
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::withdraw(
|
process_instruction_as_one_arg(&instruction::withdraw(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&solana_sdk::pubkey::new_rand(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
|
@ -524,16 +506,16 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::deactivate_stake(
|
process_instruction_as_one_arg(&instruction::deactivate_stake(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default()
|
&Pubkey::new_unique()
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::set_lockup(
|
process_instruction_as_one_arg(&instruction::set_lockup(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&LockupArgs::default(),
|
&LockupArgs::default(),
|
||||||
&Pubkey::default()
|
&Pubkey::new_unique()
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
|
@ -552,8 +534,8 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::authorize(
|
process_instruction_as_one_arg(&instruction::authorize(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
StakeAuthorize::Staker,
|
StakeAuthorize::Staker,
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
|
@ -563,9 +545,9 @@ mod tests {
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::split(
|
&instruction::split(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)[2]
|
)[2]
|
||||||
),
|
),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
|
@ -573,8 +555,8 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::split(
|
&instruction::split(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
)[2]
|
)[2]
|
||||||
|
@ -585,8 +567,8 @@ mod tests {
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::merge(
|
&instruction::merge(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)[0]
|
)[0]
|
||||||
),
|
),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
|
@ -594,9 +576,9 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::merge(
|
&instruction::merge(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)[0]
|
)[0]
|
||||||
),
|
),
|
||||||
Err(InstructionError::IncorrectProgramId),
|
Err(InstructionError::IncorrectProgramId),
|
||||||
|
@ -605,10 +587,10 @@ mod tests {
|
||||||
process_instruction_as_one_arg(
|
process_instruction_as_one_arg(
|
||||||
&instruction::split_with_seed(
|
&instruction::split_with_seed(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
"seed"
|
"seed"
|
||||||
)[1]
|
)[1]
|
||||||
),
|
),
|
||||||
|
@ -617,16 +599,16 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::delegate_stake(
|
process_instruction_as_one_arg(&instruction::delegate_stake(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::withdraw(
|
process_instruction_as_one_arg(&instruction::withdraw(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&solana_sdk::pubkey::new_rand(),
|
&Pubkey::new_unique(),
|
||||||
100,
|
100,
|
||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
|
@ -635,7 +617,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&instruction::deactivate_stake(
|
process_instruction_as_one_arg(&instruction::deactivate_stake(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&Pubkey::default()
|
&Pubkey::new_unique()
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
);
|
);
|
||||||
|
@ -643,7 +625,7 @@ mod tests {
|
||||||
process_instruction_as_one_arg(&instruction::set_lockup(
|
process_instruction_as_one_arg(&instruction::set_lockup(
|
||||||
&spoofed_stake_state_pubkey(),
|
&spoofed_stake_state_pubkey(),
|
||||||
&LockupArgs::default(),
|
&LockupArgs::default(),
|
||||||
&Pubkey::default()
|
&Pubkey::new_unique()
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
);
|
);
|
||||||
|
@ -656,7 +638,6 @@ mod tests {
|
||||||
// gets the "is_empty()" check
|
// gets the "is_empty()" check
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Initialize(
|
&serialize(&StakeInstruction::Initialize(
|
||||||
Authorized::default(),
|
Authorized::default(),
|
||||||
Lockup::default()
|
Lockup::default()
|
||||||
|
@ -668,12 +649,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// no account for rent
|
// no account for rent
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let keyed_accounts = [(false, false, &stake_address, &stake_account)];
|
let keyed_accounts = [(false, false, stake_address, stake_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Initialize(
|
&serialize(&StakeInstruction::Initialize(
|
||||||
Authorized::default(),
|
Authorized::default(),
|
||||||
Lockup::default()
|
Lockup::default()
|
||||||
|
@ -685,17 +665,16 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// rent fails to deserialize
|
// rent fails to deserialize
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let rent_address = sysvar::rent::id();
|
let rent_address = sysvar::rent::id();
|
||||||
let rent_account = create_default_account();
|
let rent_account = create_default_account();
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &rent_address, &rent_account),
|
(false, false, rent_address, rent_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Initialize(
|
&serialize(&StakeInstruction::Initialize(
|
||||||
Authorized::default(),
|
Authorized::default(),
|
||||||
Lockup::default()
|
Lockup::default()
|
||||||
|
@ -707,19 +686,18 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// fails to deserialize stake state
|
// fails to deserialize stake state
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let rent_address = sysvar::rent::id();
|
let rent_address = sysvar::rent::id();
|
||||||
let rent_account = RefCell::new(account::create_account_shared_data_for_test(
|
let rent_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&Rent::default(),
|
&Rent::default(),
|
||||||
));
|
)));
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &rent_address, &rent_account),
|
(false, false, rent_address, rent_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Initialize(
|
&serialize(&StakeInstruction::Initialize(
|
||||||
Authorized::default(),
|
Authorized::default(),
|
||||||
Lockup::default()
|
Lockup::default()
|
||||||
|
@ -731,12 +709,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// gets the first check in delegate, wrong number of accounts
|
// gets the first check in delegate, wrong number of accounts
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let keyed_accounts = [(false, false, &stake_address, &stake_account)];
|
let keyed_accounts = [(false, false, stake_address, stake_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -744,12 +721,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// gets the sub-check for number of args
|
// gets the sub-check for number of args
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let keyed_accounts = [(false, false, &stake_address, &stake_account)];
|
let keyed_accounts = [(false, false, stake_address, stake_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -757,34 +733,33 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// gets the check non-deserialize-able account in delegate_stake
|
// gets the check non-deserialize-able account in delegate_stake
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let vote_address = Pubkey::default();
|
let vote_address = Pubkey::new_unique();
|
||||||
let mut bad_vote_account = create_default_account();
|
let vote_account = AccountSharedData::new_ref(0, 0, &solana_vote_program::id());
|
||||||
bad_vote_account
|
|
||||||
.get_mut()
|
|
||||||
.set_owner(solana_vote_program::id());
|
|
||||||
let clock_address = sysvar::clock::id();
|
let clock_address = sysvar::clock::id();
|
||||||
let clock_account = RefCell::new(account::create_account_shared_data_for_test(
|
let clock_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&sysvar::clock::Clock::default(),
|
&sysvar::clock::Clock::default(),
|
||||||
));
|
)));
|
||||||
let stake_history_address = sysvar::stake_history::id();
|
let stake_history_address = sysvar::stake_history::id();
|
||||||
let stake_history_account = RefCell::new(account::create_account_shared_data_for_test(
|
let stake_history_account =
|
||||||
|
Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&sysvar::stake_history::StakeHistory::default(),
|
&sysvar::stake_history::StakeHistory::default(),
|
||||||
));
|
)));
|
||||||
let config_address = stake_config::id();
|
let config_address = stake_config::id();
|
||||||
let config_account =
|
let config_account = Rc::new(RefCell::new(config::create_account(
|
||||||
RefCell::new(config::create_account(0, &stake_config::Config::default()));
|
0,
|
||||||
|
&stake_config::Config::default(),
|
||||||
|
)));
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(true, false, &stake_address, &stake_account),
|
(true, false, stake_address, stake_account),
|
||||||
(false, false, &vote_address, &bad_vote_account),
|
(false, false, vote_address, vote_account),
|
||||||
(false, false, &clock_address, &clock_account),
|
(false, false, clock_address, clock_account),
|
||||||
(false, false, &stake_history_address, &stake_history_account),
|
(false, false, stake_history_address, stake_history_account),
|
||||||
(false, false, &config_address, &config_account),
|
(false, false, config_address, config_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -792,27 +767,26 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tests 3rd keyed account is of correct type (Clock instead of rewards) in withdraw
|
// Tests 3rd keyed account is of correct type (Clock instead of rewards) in withdraw
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let vote_address = Pubkey::default();
|
let vote_address = Pubkey::new_unique();
|
||||||
let vote_account = create_default_account();
|
let vote_account = create_default_account();
|
||||||
let rewards_address = sysvar::rewards::id();
|
let rewards_address = sysvar::rewards::id();
|
||||||
let rewards_account = RefCell::new(account::create_account_shared_data_for_test(
|
let rewards_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&sysvar::rewards::Rewards::new(0.0),
|
&sysvar::rewards::Rewards::new(0.0),
|
||||||
));
|
)));
|
||||||
let stake_history_address = sysvar::stake_history::id();
|
let stake_history_address = sysvar::stake_history::id();
|
||||||
let stake_history_account = RefCell::new(account::create_account_shared_data_for_test(
|
let stake_history_account = Rc::new(RefCell::new(
|
||||||
&StakeHistory::default(),
|
account::create_account_shared_data_for_test(&StakeHistory::default()),
|
||||||
));
|
));
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &vote_address, &vote_account),
|
(false, false, vote_address, vote_account),
|
||||||
(false, false, &rewards_address, &rewards_account),
|
(false, false, rewards_address, rewards_account),
|
||||||
(false, false, &stake_history_address, &stake_history_account),
|
(false, false, stake_history_address, stake_history_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
|
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -820,12 +794,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tests correct number of accounts are provided in withdraw
|
// Tests correct number of accounts are provided in withdraw
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let keyed_accounts = [(false, false, &stake_address, &stake_account)];
|
let keyed_accounts = [(false, false, stake_address, stake_account)];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
|
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -833,19 +806,18 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tests 2nd keyed account is of correct type (Clock instead of rewards) in deactivate
|
// Tests 2nd keyed account is of correct type (Clock instead of rewards) in deactivate
|
||||||
let stake_address = Pubkey::default();
|
let stake_address = Pubkey::new_unique();
|
||||||
let stake_account = create_default_stake_account();
|
let stake_account = create_default_stake_account();
|
||||||
let rewards_address = sysvar::rewards::id();
|
let rewards_address = sysvar::rewards::id();
|
||||||
let rewards_account = RefCell::new(account::create_account_shared_data_for_test(
|
let rewards_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&sysvar::rewards::Rewards::new(0.0),
|
&sysvar::rewards::Rewards::new(0.0),
|
||||||
));
|
)));
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &rewards_address, &rewards_account),
|
(false, false, rewards_address, rewards_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Deactivate).unwrap(),
|
&serialize(&StakeInstruction::Deactivate).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -854,11 +826,7 @@ mod tests {
|
||||||
|
|
||||||
// Tests correct number of accounts are provided in deactivate
|
// Tests correct number of accounts are provided in deactivate
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(&serialize(&StakeInstruction::Deactivate).unwrap(), &[]),
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::Deactivate).unwrap(),
|
|
||||||
&[],
|
|
||||||
),
|
|
||||||
Err(InstructionError::NotEnoughAccountKeys),
|
Err(InstructionError::NotEnoughAccountKeys),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -885,21 +853,20 @@ mod tests {
|
||||||
&id(),
|
&id(),
|
||||||
);
|
);
|
||||||
let rent_address = sysvar::rent::id();
|
let rent_address = sysvar::rent::id();
|
||||||
let rent_account = RefCell::new(account::create_account_shared_data_for_test(
|
let rent_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&Rent::default(),
|
&Rent::default(),
|
||||||
));
|
)));
|
||||||
let staker_account = create_default_account();
|
let staker_account = create_default_account();
|
||||||
let withdrawer_account = create_default_account();
|
let withdrawer_account = create_default_account();
|
||||||
|
|
||||||
let keyed_accounts: [(bool, bool, &Pubkey, &RefCell<AccountSharedData>); 4] = [
|
let keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &rent_address, &rent_account),
|
(false, false, rent_address, rent_account),
|
||||||
(false, false, &staker, &staker_account),
|
(false, false, staker, staker_account),
|
||||||
(true, false, &withdrawer, &withdrawer_account),
|
(true, false, withdrawer, withdrawer_account.clone()),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::InitializeChecked).unwrap(),
|
&serialize(&StakeInstruction::InitializeChecked).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -935,39 +902,39 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test AuthorizeChecked with authority signer
|
// Test AuthorizeChecked with authority signer
|
||||||
let stake_account = AccountSharedData::new_ref_data_with_space(
|
let stake_account = Rc::new(
|
||||||
|
AccountSharedData::new_ref_data_with_space(
|
||||||
42,
|
42,
|
||||||
&StakeState::Initialized(Meta::auto(&authorized_address)),
|
&StakeState::Initialized(Meta::auto(&authorized_address)),
|
||||||
std::mem::size_of::<StakeState>(),
|
std::mem::size_of::<StakeState>(),
|
||||||
&id(),
|
&id(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
|
);
|
||||||
let clock_address = sysvar::clock::id();
|
let clock_address = sysvar::clock::id();
|
||||||
let clock_account = RefCell::new(account::create_account_shared_data_for_test(
|
let clock_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&Clock::default(),
|
&Clock::default(),
|
||||||
));
|
)));
|
||||||
let authorized_account = create_default_account();
|
let authorized_account = create_default_account();
|
||||||
let new_authorized_account = create_default_account();
|
let new_authorized_account = create_default_account();
|
||||||
|
|
||||||
let mut keyed_accounts = [
|
let mut keyed_accounts = [
|
||||||
(false, false, &stake_address, &stake_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &clock_address, &clock_account),
|
(false, false, clock_address, clock_account.clone()),
|
||||||
(true, false, &authorized_address, &authorized_account),
|
(true, false, authorized_address, authorized_account.clone()),
|
||||||
(true, false, &staker, &new_authorized_account),
|
(true, false, staker, new_authorized_account.clone()),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::AuthorizeChecked(StakeAuthorize::Staker)).unwrap(),
|
&serialize(&StakeInstruction::AuthorizeChecked(StakeAuthorize::Staker)).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
|
|
||||||
keyed_accounts[3] = (true, false, &withdrawer, &new_authorized_account);
|
keyed_accounts[3] = (true, false, withdrawer, new_authorized_account.clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::AuthorizeChecked(
|
&serialize(&StakeInstruction::AuthorizeChecked(
|
||||||
StakeAuthorize::Withdrawer
|
StakeAuthorize::Withdrawer
|
||||||
))
|
))
|
||||||
|
@ -1013,22 +980,23 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test AuthorizeCheckedWithSeed with authority signer
|
// Test AuthorizeCheckedWithSeed with authority signer
|
||||||
let stake_account = AccountSharedData::new_ref_data_with_space(
|
let stake_account = Rc::new(
|
||||||
|
AccountSharedData::new_ref_data_with_space(
|
||||||
42,
|
42,
|
||||||
&StakeState::Initialized(Meta::auto(&address_with_seed)),
|
&StakeState::Initialized(Meta::auto(&address_with_seed)),
|
||||||
std::mem::size_of::<StakeState>(),
|
std::mem::size_of::<StakeState>(),
|
||||||
&id(),
|
&id(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
|
);
|
||||||
let mut keyed_accounts = [
|
let mut keyed_accounts = [
|
||||||
(false, false, &address_with_seed, &stake_account),
|
(false, false, address_with_seed, stake_account),
|
||||||
(true, false, &authorized_owner, &authorized_account),
|
(true, false, authorized_owner, authorized_account),
|
||||||
(false, false, &clock_address, &clock_account),
|
(false, false, clock_address, clock_account),
|
||||||
(true, false, &staker, &new_authorized_account),
|
(true, false, staker, new_authorized_account.clone()),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::AuthorizeCheckedWithSeed(
|
&serialize(&StakeInstruction::AuthorizeCheckedWithSeed(
|
||||||
AuthorizeCheckedWithSeedArgs {
|
AuthorizeCheckedWithSeedArgs {
|
||||||
stake_authorize: StakeAuthorize::Staker,
|
stake_authorize: StakeAuthorize::Staker,
|
||||||
|
@ -1042,10 +1010,9 @@ mod tests {
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
|
|
||||||
keyed_accounts[3] = (true, false, &withdrawer, &new_authorized_account);
|
keyed_accounts[3] = (true, false, withdrawer, new_authorized_account);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&StakeInstruction::AuthorizeCheckedWithSeed(
|
&serialize(&StakeInstruction::AuthorizeCheckedWithSeed(
|
||||||
AuthorizeCheckedWithSeedArgs {
|
AuthorizeCheckedWithSeedArgs {
|
||||||
stake_authorize: StakeAuthorize::Withdrawer,
|
stake_authorize: StakeAuthorize::Withdrawer,
|
||||||
|
@ -1077,42 +1044,45 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test SetLockupChecked with lockup custodian signer
|
// Test SetLockupChecked with lockup custodian signer
|
||||||
let stake_account = AccountSharedData::new_ref_data_with_space(
|
let stake_account = Rc::new(
|
||||||
|
AccountSharedData::new_ref_data_with_space(
|
||||||
42,
|
42,
|
||||||
&StakeState::Initialized(Meta::auto(&withdrawer)),
|
&StakeState::Initialized(Meta::auto(&withdrawer)),
|
||||||
std::mem::size_of::<StakeState>(),
|
std::mem::size_of::<StakeState>(),
|
||||||
&id(),
|
&id(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
|
);
|
||||||
let custodian_account = create_default_account();
|
let custodian_account = create_default_account();
|
||||||
|
|
||||||
let processor_account = RefCell::new(AccountSharedData::from(Account {
|
|
||||||
owner: solana_sdk::native_loader::id(),
|
|
||||||
..Account::default()
|
|
||||||
}));
|
|
||||||
let keyed_accounts = [
|
let keyed_accounts = [
|
||||||
(false, false, &id(), &processor_account),
|
(false, false, stake_address, stake_account),
|
||||||
(false, false, &stake_address, &stake_account),
|
(true, false, withdrawer, withdrawer_account),
|
||||||
(true, false, &withdrawer, &withdrawer_account),
|
(true, false, custodian, custodian_account),
|
||||||
(true, false, &custodian, &custodian_account),
|
|
||||||
];
|
];
|
||||||
let mut invoke_context =
|
let mut preparation = prepare_mock_invoke_context(&[], &instruction.data, &keyed_accounts);
|
||||||
MockInvokeContext::new(&id(), create_keyed_accounts_unified(&keyed_accounts));
|
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
|
||||||
|
let program_indices = vec![preparation.accounts.len()];
|
||||||
|
preparation.accounts.push((id(), processor_account));
|
||||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||||
let sysvars = &[(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
invoke_context.sysvars = sysvars;
|
let mut invoke_context = ThisInvokeContext::new_mock_with_sysvars_and_features(
|
||||||
|
&preparation.accounts,
|
||||||
|
&[],
|
||||||
|
&sysvars,
|
||||||
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
|
);
|
||||||
|
invoke_context
|
||||||
|
.push(
|
||||||
|
&preparation.message,
|
||||||
|
&preparation.message.instructions[0],
|
||||||
|
&program_indices,
|
||||||
|
Some(&preparation.account_indices),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::process_instruction(
|
super::process_instruction(1, &instruction.data, &mut invoke_context),
|
||||||
1,
|
|
||||||
&serialize(&StakeInstruction::SetLockupChecked(LockupCheckedArgs {
|
|
||||||
unix_timestamp: None,
|
|
||||||
epoch: Some(1),
|
|
||||||
}))
|
|
||||||
.unwrap(),
|
|
||||||
&mut invoke_context,
|
|
||||||
),
|
|
||||||
Ok(()),
|
Ok(()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1373,11 +1373,11 @@ fn do_create_account(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
use solana_program_runtime::invoke_context::ThisInvokeContext;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{AccountSharedData, WritableAccount},
|
account::{AccountSharedData, WritableAccount},
|
||||||
clock::UnixTimestamp,
|
clock::UnixTimestamp,
|
||||||
native_token,
|
native_token,
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_program,
|
system_program,
|
||||||
};
|
};
|
||||||
|
@ -5069,13 +5069,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge() {
|
fn test_merge() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let stake_lamports = 42;
|
let stake_lamports = 42;
|
||||||
|
|
||||||
let signers = vec![authorized_pubkey].into_iter().collect();
|
let signers = vec![authorized_pubkey].into_iter().collect();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
for state in &[
|
for state in &[
|
||||||
StakeState::Initialized(Meta::auto(&authorized_pubkey)),
|
StakeState::Initialized(Meta::auto(&authorized_pubkey)),
|
||||||
|
@ -5179,7 +5179,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_self_fails() {
|
fn test_merge_self_fails() {
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let stake_address = Pubkey::new_unique();
|
let stake_address = Pubkey::new_unique();
|
||||||
let authority_pubkey = Pubkey::new_unique();
|
let authority_pubkey = Pubkey::new_unique();
|
||||||
let signers = HashSet::from_iter(vec![authority_pubkey]);
|
let signers = HashSet::from_iter(vec![authority_pubkey]);
|
||||||
|
@ -5224,6 +5224,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_incorrect_authorized_staker() {
|
fn test_merge_incorrect_authorized_staker() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
|
@ -5232,7 +5233,6 @@ mod tests {
|
||||||
|
|
||||||
let signers = vec![authorized_pubkey].into_iter().collect();
|
let signers = vec![authorized_pubkey].into_iter().collect();
|
||||||
let wrong_signers = vec![wrong_authorized_pubkey].into_iter().collect();
|
let wrong_signers = vec![wrong_authorized_pubkey].into_iter().collect();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
for state in &[
|
for state in &[
|
||||||
StakeState::Initialized(Meta::auto(&authorized_pubkey)),
|
StakeState::Initialized(Meta::auto(&authorized_pubkey)),
|
||||||
|
@ -5293,12 +5293,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_invalid_account_data() {
|
fn test_merge_invalid_account_data() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let stake_lamports = 42;
|
let stake_lamports = 42;
|
||||||
let signers = vec![authorized_pubkey].into_iter().collect();
|
let signers = vec![authorized_pubkey].into_iter().collect();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
for state in &[
|
for state in &[
|
||||||
StakeState::Uninitialized,
|
StakeState::Uninitialized,
|
||||||
|
@ -5343,6 +5343,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_fake_stake_source() {
|
fn test_merge_fake_stake_source() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
let stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
let source_stake_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
let authorized_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
|
@ -5368,7 +5369,6 @@ mod tests {
|
||||||
.expect("source_stake_account");
|
.expect("source_stake_account");
|
||||||
let source_stake_keyed_account =
|
let source_stake_keyed_account =
|
||||||
KeyedAccount::new(&source_stake_pubkey, true, &source_stake_account);
|
KeyedAccount::new(&source_stake_pubkey, true, &source_stake_account);
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.merge(
|
stake_keyed_account.merge(
|
||||||
|
@ -5385,6 +5385,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_active_stake() {
|
fn test_merge_active_stake() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let base_lamports = 4242424242;
|
let base_lamports = 4242424242;
|
||||||
let stake_address = Pubkey::new_unique();
|
let stake_address = Pubkey::new_unique();
|
||||||
let source_address = Pubkey::new_unique();
|
let source_address = Pubkey::new_unique();
|
||||||
|
@ -5438,7 +5439,6 @@ mod tests {
|
||||||
|
|
||||||
let mut clock = Clock::default();
|
let mut clock = Clock::default();
|
||||||
let mut stake_history = StakeHistory::default();
|
let mut stake_history = StakeHistory::default();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
clock.epoch = 0;
|
clock.epoch = 0;
|
||||||
let mut effective = base_lamports;
|
let mut effective = base_lamports;
|
||||||
|
@ -6007,6 +6007,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_things_can_merge() {
|
fn test_things_can_merge() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let good_stake = Stake {
|
let good_stake = Stake {
|
||||||
credits_observed: 4242,
|
credits_observed: 4242,
|
||||||
delegation: Delegation {
|
delegation: Delegation {
|
||||||
|
@ -6016,7 +6017,6 @@ mod tests {
|
||||||
..Delegation::default()
|
..Delegation::default()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
let identical = good_stake;
|
let identical = good_stake;
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -6105,7 +6105,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_metas_can_merge_pre_v4() {
|
fn test_metas_can_merge_pre_v4() {
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
// Identical Metas can merge
|
// Identical Metas can merge
|
||||||
assert!(MergeKind::metas_can_merge(
|
assert!(MergeKind::metas_can_merge(
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -6191,7 +6191,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_metas_can_merge_v4() {
|
fn test_metas_can_merge_v4() {
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
// Identical Metas can merge
|
// Identical Metas can merge
|
||||||
assert!(MergeKind::metas_can_merge(
|
assert!(MergeKind::metas_can_merge(
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -6337,6 +6337,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_kind_get_if_mergeable() {
|
fn test_merge_kind_get_if_mergeable() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let authority_pubkey = Pubkey::new_unique();
|
let authority_pubkey = Pubkey::new_unique();
|
||||||
let initial_lamports = 4242424242;
|
let initial_lamports = 4242424242;
|
||||||
let rent = Rent::default();
|
let rent = Rent::default();
|
||||||
|
@ -6357,7 +6358,6 @@ mod tests {
|
||||||
let stake_keyed_account = KeyedAccount::new(&authority_pubkey, true, &stake_account);
|
let stake_keyed_account = KeyedAccount::new(&authority_pubkey, true, &stake_account);
|
||||||
let mut clock = Clock::default();
|
let mut clock = Clock::default();
|
||||||
let mut stake_history = StakeHistory::default();
|
let mut stake_history = StakeHistory::default();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
// Uninitialized state fails
|
// Uninitialized state fails
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -6569,6 +6569,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_kind_merge() {
|
fn test_merge_kind_merge() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let lamports = 424242;
|
let lamports = 424242;
|
||||||
let meta = Meta {
|
let meta = Meta {
|
||||||
rent_exempt_reserve: 42,
|
rent_exempt_reserve: 42,
|
||||||
|
@ -6584,7 +6585,6 @@ mod tests {
|
||||||
let inactive = MergeKind::Inactive(Meta::default(), lamports);
|
let inactive = MergeKind::Inactive(Meta::default(), lamports);
|
||||||
let activation_epoch = MergeKind::ActivationEpoch(meta, stake);
|
let activation_epoch = MergeKind::ActivationEpoch(meta, stake);
|
||||||
let fully_active = MergeKind::FullyActive(meta, stake);
|
let fully_active = MergeKind::FullyActive(meta, stake);
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
inactive
|
inactive
|
||||||
|
@ -6647,6 +6647,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_active_stake_merge() {
|
fn test_active_stake_merge() {
|
||||||
|
let invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let delegation_a = 4_242_424_242u64;
|
let delegation_a = 4_242_424_242u64;
|
||||||
let delegation_b = 6_200_000_000u64;
|
let delegation_b = 6_200_000_000u64;
|
||||||
let credits_a = 124_521_000u64;
|
let credits_a = 124_521_000u64;
|
||||||
|
@ -6670,8 +6671,6 @@ mod tests {
|
||||||
credits_observed: credits_a,
|
credits_observed: credits_a,
|
||||||
};
|
};
|
||||||
|
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
|
|
||||||
// activating stake merge, match credits observed
|
// activating stake merge, match credits observed
|
||||||
let activation_epoch_a = MergeKind::ActivationEpoch(meta, stake_a);
|
let activation_epoch_a = MergeKind::ActivationEpoch(meta, stake_a);
|
||||||
let activation_epoch_b = MergeKind::ActivationEpoch(meta, stake_b);
|
let activation_epoch_b = MergeKind::ActivationEpoch(meta, stake_b);
|
||||||
|
|
|
@ -23,6 +23,9 @@ solana-metrics = { path = "../../metrics", version = "=1.9.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
solana-sdk = { path = "../../sdk", version = "=1.9.0" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
solana-program-runtime = { path = "../../program-runtime", version = "=1.9.0" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
rustc_version = "0.4"
|
rustc_version = "0.4"
|
||||||
|
|
||||||
|
|
|
@ -405,41 +405,37 @@ pub fn process_instruction(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
|
use solana_program_runtime::invoke_context::mock_process_instruction;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{self, Account, AccountSharedData},
|
account::{self, Account, AccountSharedData},
|
||||||
keyed_account::create_keyed_accounts_unified,
|
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
fn create_default_account() -> RefCell<AccountSharedData> {
|
fn create_default_account() -> Rc<RefCell<AccountSharedData>> {
|
||||||
RefCell::new(AccountSharedData::default())
|
AccountSharedData::new_ref(0, 0, &Pubkey::new_unique())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_instruction(
|
fn process_instruction(
|
||||||
owner: &Pubkey,
|
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
|
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
|
mock_process_instruction(
|
||||||
let mut keyed_accounts = keyed_accounts.to_vec();
|
&id(),
|
||||||
keyed_accounts.insert(0, (false, false, owner, &processor_account));
|
Vec::new(),
|
||||||
super::process_instruction(
|
|
||||||
1,
|
|
||||||
instruction_data,
|
instruction_data,
|
||||||
&mut MockInvokeContext::new(owner, create_keyed_accounts_unified(&keyed_accounts)),
|
keyed_accounts,
|
||||||
|
super::process_instruction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::same_item_push)]
|
|
||||||
fn process_instruction_as_one_arg(instruction: &Instruction) -> Result<(), InstructionError> {
|
fn process_instruction_as_one_arg(instruction: &Instruction) -> Result<(), InstructionError> {
|
||||||
let mut accounts: Vec<_> = instruction
|
let mut accounts: Vec<_> = instruction
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|meta| {
|
.map(|meta| {
|
||||||
RefCell::new(if sysvar::clock::check_id(&meta.pubkey) {
|
Rc::new(RefCell::new(if sysvar::clock::check_id(&meta.pubkey) {
|
||||||
account::create_account_shared_data_for_test(&Clock::default())
|
account::create_account_shared_data_for_test(&Clock::default())
|
||||||
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
||||||
account::create_account_shared_data_for_test(&SlotHashes::default())
|
account::create_account_shared_data_for_test(&SlotHashes::default())
|
||||||
|
@ -455,22 +451,26 @@ mod tests {
|
||||||
owner: id(),
|
owner: id(),
|
||||||
..Account::default()
|
..Account::default()
|
||||||
})
|
})
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
#[allow(clippy::same_item_push)]
|
||||||
for _ in 0..instruction.accounts.len() {
|
for _ in 0..instruction.accounts.len() {
|
||||||
accounts.push(RefCell::new(AccountSharedData::default()));
|
accounts.push(AccountSharedData::new_ref(0, 0, &Pubkey::new_unique()));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
let keyed_accounts: Vec<_> = instruction
|
let keyed_accounts: Vec<_> = instruction
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.zip(accounts.iter())
|
.zip(accounts.into_iter())
|
||||||
.map(|(meta, account)| (meta.is_signer, false, &meta.pubkey, account))
|
.map(|(meta, account)| (meta.is_signer, meta.is_writable, meta.pubkey, account))
|
||||||
.collect();
|
.collect();
|
||||||
process_instruction(&Pubkey::default(), &instruction.data, &keyed_accounts)
|
solana_program_runtime::invoke_context::mock_process_instruction(
|
||||||
}
|
&id(),
|
||||||
|
Vec::new(),
|
||||||
|
&instruction.data,
|
||||||
|
&keyed_accounts,
|
||||||
|
super::process_instruction,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_vote_state_pubkey() -> Pubkey {
|
fn invalid_vote_state_pubkey() -> Pubkey {
|
||||||
|
@ -481,7 +481,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vote_process_instruction_decode_bail() {
|
fn test_vote_process_instruction_decode_bail() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&Pubkey::default(), &[], &[]),
|
process_instruction(&[], &[]),
|
||||||
Err(InstructionError::NotEnoughAccountKeys),
|
Err(InstructionError::NotEnoughAccountKeys),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&vote(
|
process_instruction_as_one_arg(&vote(
|
||||||
&invalid_vote_state_pubkey(),
|
&invalid_vote_state_pubkey(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
Vote::default(),
|
Vote::default(),
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountOwner),
|
Err(InstructionError::InvalidAccountOwner),
|
||||||
|
@ -502,8 +502,8 @@ mod tests {
|
||||||
fn test_vote_process_instruction() {
|
fn test_vote_process_instruction() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let instructions = create_account(
|
let instructions = create_account(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&VoteInit::default(),
|
&VoteInit::default(),
|
||||||
100,
|
100,
|
||||||
);
|
);
|
||||||
|
@ -513,16 +513,16 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&vote(
|
process_instruction_as_one_arg(&vote(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
Vote::default(),
|
Vote::default(),
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&vote_switch(
|
process_instruction_as_one_arg(&vote_switch(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
Vote::default(),
|
Vote::default(),
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
)),
|
)),
|
||||||
|
@ -530,25 +530,25 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&authorize(
|
process_instruction_as_one_arg(&authorize(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
VoteAuthorize::Voter,
|
VoteAuthorize::Voter,
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&update_validator_identity(
|
process_instruction_as_one_arg(&update_validator_identity(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&update_commission(
|
process_instruction_as_one_arg(&update_commission(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
0,
|
0,
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
@ -556,10 +556,10 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction_as_one_arg(&withdraw(
|
process_instruction_as_one_arg(&withdraw(
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
&Pubkey::default(),
|
&Pubkey::new_unique(),
|
||||||
0,
|
0,
|
||||||
&Pubkey::default()
|
&Pubkey::new_unique()
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
|
@ -624,21 +624,20 @@ mod tests {
|
||||||
// Test with new_authorized_pubkey signer
|
// Test with new_authorized_pubkey signer
|
||||||
let vote_account = AccountSharedData::new_ref(100, VoteState::size_of(), &id());
|
let vote_account = AccountSharedData::new_ref(100, VoteState::size_of(), &id());
|
||||||
let clock_address = sysvar::clock::id();
|
let clock_address = sysvar::clock::id();
|
||||||
let clock_account = RefCell::new(account::create_account_shared_data_for_test(
|
let clock_account = Rc::new(RefCell::new(account::create_account_shared_data_for_test(
|
||||||
&Clock::default(),
|
&Clock::default(),
|
||||||
));
|
)));
|
||||||
let default_authorized_pubkey = Pubkey::default();
|
let default_authorized_pubkey = Pubkey::default();
|
||||||
let authorized_account = create_default_account();
|
let authorized_account = create_default_account();
|
||||||
let new_authorized_account = create_default_account();
|
let new_authorized_account = create_default_account();
|
||||||
let keyed_accounts: [(bool, bool, &Pubkey, &RefCell<AccountSharedData>); 4] = [
|
let keyed_accounts = [
|
||||||
(false, false, &vote_pubkey, &vote_account),
|
(false, false, vote_pubkey, vote_account),
|
||||||
(false, false, &clock_address, &clock_account),
|
(false, false, clock_address, clock_account),
|
||||||
(true, false, &default_authorized_pubkey, &authorized_account),
|
(true, false, default_authorized_pubkey, authorized_account),
|
||||||
(true, false, &new_authorized_pubkey, &new_authorized_account),
|
(true, false, new_authorized_pubkey, new_authorized_account),
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&VoteInstruction::AuthorizeChecked(VoteAuthorize::Voter)).unwrap(),
|
&serialize(&VoteInstruction::AuthorizeChecked(VoteAuthorize::Voter)).unwrap(),
|
||||||
&keyed_accounts,
|
&keyed_accounts,
|
||||||
),
|
),
|
||||||
|
@ -647,7 +646,6 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
process_instruction(
|
||||||
&Pubkey::default(),
|
|
||||||
&serialize(&VoteInstruction::AuthorizeChecked(
|
&serialize(&VoteInstruction::AuthorizeChecked(
|
||||||
VoteAuthorize::Withdrawer
|
VoteAuthorize::Withdrawer
|
||||||
))
|
))
|
||||||
|
|
|
@ -14,6 +14,7 @@ serde = "1.0.130"
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.68"
|
||||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.9.0" }
|
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.9.0" }
|
||||||
solana-logger = { path = "../logger", version = "=1.9.0" }
|
solana-logger = { path = "../logger", version = "=1.9.0" }
|
||||||
|
solana-program-runtime = { path = "../program-runtime", version = "=1.9.0" }
|
||||||
solana-sdk = { path = "../sdk", version = "=1.9.0" }
|
solana-sdk = { path = "../sdk", version = "=1.9.0" }
|
||||||
solana_rbpf = "=0.2.14"
|
solana_rbpf = "=0.2.14"
|
||||||
time = "0.3.4"
|
time = "0.3.4"
|
||||||
|
|
|
@ -5,6 +5,7 @@ use solana_bpf_loader_program::{
|
||||||
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
|
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
|
||||||
ThisInstructionMeter,
|
ThisInstructionMeter,
|
||||||
};
|
};
|
||||||
|
use solana_program_runtime::invoke_context::{prepare_mock_invoke_context, ThisInvokeContext};
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
assembler::assemble,
|
assembler::assemble,
|
||||||
static_analysis::Analysis,
|
static_analysis::Analysis,
|
||||||
|
@ -12,32 +13,31 @@ use solana_rbpf::{
|
||||||
vm::{Config, DynamicAnalysis, Executable},
|
vm::{Config, DynamicAnalysis, Executable},
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::AccountSharedData,
|
account::AccountSharedData, bpf_loader, process_instruction::InvokeContext, pubkey::Pubkey,
|
||||||
bpf_loader,
|
|
||||||
keyed_account::KeyedAccount,
|
|
||||||
process_instruction::{InvokeContext, MockInvokeContext},
|
|
||||||
pubkey::Pubkey,
|
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, fs::File, io::Read, io::Seek, io::SeekFrom, path::Path};
|
use std::{fs::File, io::Read, io::Seek, io::SeekFrom, path::Path};
|
||||||
use time::Instant;
|
use time::Instant;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct Account {
|
struct Account {
|
||||||
|
key: Pubkey,
|
||||||
|
owner: Pubkey,
|
||||||
|
is_signer: bool,
|
||||||
|
is_writable: bool,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
owner: Pubkey,
|
|
||||||
}
|
}
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Input {
|
struct Input {
|
||||||
accounts: Vec<Account>,
|
accounts: Vec<Account>,
|
||||||
insndata: Vec<u8>,
|
instruction_data: Vec<u8>,
|
||||||
}
|
}
|
||||||
fn load_accounts(path: &Path) -> Result<Input> {
|
fn load_accounts(path: &Path) -> Result<Input> {
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
let input: Input = serde_json::from_reader(file)?;
|
let input: Input = serde_json::from_reader(file)?;
|
||||||
println!("Program input:");
|
println!("Program input:");
|
||||||
println!("accounts {:?}", &input.accounts);
|
println!("accounts {:?}", &input.accounts);
|
||||||
println!("insndata {:?}", &input.insndata);
|
println!("instruction_data {:?}", &input.instruction_data);
|
||||||
println!("----------------------------------------");
|
println!("----------------------------------------");
|
||||||
Ok(input)
|
Ok(input)
|
||||||
}
|
}
|
||||||
|
@ -59,15 +59,21 @@ and the following fields are required
|
||||||
{
|
{
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"lamports": 1000,
|
"key": [
|
||||||
"data": [0, 0, 0, 3],
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
],
|
||||||
"owner": [
|
"owner": [
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
]
|
],
|
||||||
|
"is_signer": false,
|
||||||
|
"is_writable": true,
|
||||||
|
"lamports": 1000,
|
||||||
|
"data": [0, 0, 0, 3]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"insndata": []
|
"instruction_data": []
|
||||||
}
|
}
|
||||||
"##,
|
"##,
|
||||||
)
|
)
|
||||||
|
@ -149,34 +155,69 @@ native machine code before execting it in the virtual machine.",
|
||||||
enable_instruction_tracing: matches.is_present("trace") || matches.is_present("profile"),
|
enable_instruction_tracing: matches.is_present("trace") || matches.is_present("profile"),
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut accounts = Vec::new();
|
let loader_id = bpf_loader::id();
|
||||||
let mut account_refcells = Vec::new();
|
let mut keyed_accounts = vec![
|
||||||
let default_account = RefCell::new(AccountSharedData::default());
|
(
|
||||||
let key = solana_sdk::pubkey::new_rand();
|
false,
|
||||||
let (mut mem, account_lengths) = match matches.value_of("input").unwrap().parse::<usize>() {
|
false,
|
||||||
Ok(allocate) => {
|
loader_id,
|
||||||
accounts.push(KeyedAccount::new(&key, false, &default_account));
|
AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id()),
|
||||||
(vec![0u8; allocate], vec![allocate])
|
),
|
||||||
|
(
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
AccountSharedData::new_ref(0, 0, &loader_id),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
let instruction_data = match matches.value_of("input").unwrap().parse::<usize>() {
|
||||||
|
Ok(allocation_size) => {
|
||||||
|
keyed_accounts.push((
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
AccountSharedData::new_ref(0, allocation_size, &Pubkey::new_unique()),
|
||||||
|
));
|
||||||
|
vec![]
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let input = load_accounts(Path::new(matches.value_of("input").unwrap())).unwrap();
|
let input = load_accounts(Path::new(matches.value_of("input").unwrap())).unwrap();
|
||||||
for acc in input.accounts {
|
for account in input.accounts {
|
||||||
let asd = AccountSharedData::new_ref(acc.lamports, acc.data.len(), &acc.owner);
|
let account_refcell = AccountSharedData::new_ref(
|
||||||
asd.borrow_mut().set_data(acc.data);
|
account.lamports,
|
||||||
account_refcells.push(asd);
|
account.data.len(),
|
||||||
|
&account.owner,
|
||||||
|
);
|
||||||
|
account_refcell.borrow_mut().set_data(account.data);
|
||||||
|
keyed_accounts.push((
|
||||||
|
account.is_signer,
|
||||||
|
account.is_writable,
|
||||||
|
account.key,
|
||||||
|
account_refcell,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
for acc in &account_refcells {
|
input.instruction_data
|
||||||
accounts.push(KeyedAccount::new(&key, false, acc));
|
|
||||||
}
|
|
||||||
let lid = bpf_loader::id();
|
|
||||||
let pid = Pubkey::new(&[0u8; 32]);
|
|
||||||
let (mut bytes, account_lengths) =
|
|
||||||
serialize_parameters(&lid, &pid, &accounts, &input.insndata).unwrap();
|
|
||||||
(Vec::from(bytes.as_slice_mut()), account_lengths)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut invoke_context = MockInvokeContext::new(&bpf_loader::id(), accounts);
|
let program_indices = [0, 1];
|
||||||
let logger = invoke_context.logger.clone();
|
let preparation = prepare_mock_invoke_context(&program_indices, &[], &keyed_accounts);
|
||||||
|
let mut invoke_context = ThisInvokeContext::new_mock(&preparation.accounts, &[]);
|
||||||
|
invoke_context
|
||||||
|
.push(
|
||||||
|
&preparation.message,
|
||||||
|
&preparation.message.instructions[0],
|
||||||
|
&program_indices,
|
||||||
|
Some(&preparation.account_indices),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
|
let (mut parameter_bytes, account_lengths) = serialize_parameters(
|
||||||
|
keyed_accounts[0].unsigned_key(),
|
||||||
|
keyed_accounts[1].unsigned_key(),
|
||||||
|
&keyed_accounts[2..],
|
||||||
|
&instruction_data,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
|
|
||||||
|
@ -231,11 +272,12 @@ native machine code before execting it in the virtual machine.",
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&id,
|
&id,
|
||||||
executable.as_ref(),
|
executable.as_ref(),
|
||||||
&mut mem,
|
parameter_bytes.as_slice_mut(),
|
||||||
&mut invoke_context,
|
&mut invoke_context,
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("Program output:");
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let result = if matches.value_of("use").unwrap() == "interpreter" {
|
let result = if matches.value_of("use").unwrap() == "interpreter" {
|
||||||
vm.execute_program_interpreted(&mut instruction_meter)
|
vm.execute_program_interpreted(&mut instruction_meter)
|
||||||
|
@ -243,13 +285,6 @@ native machine code before execting it in the virtual machine.",
|
||||||
vm.execute_program_jit(&mut instruction_meter)
|
vm.execute_program_jit(&mut instruction_meter)
|
||||||
};
|
};
|
||||||
let duration = Instant::now() - start_time;
|
let duration = Instant::now() - start_time;
|
||||||
if logger.log.borrow().len() > 0 {
|
|
||||||
println!("Program output:");
|
|
||||||
for s in logger.log.borrow_mut().iter() {
|
|
||||||
println!("{}", s);
|
|
||||||
}
|
|
||||||
println!("----------------------------------------");
|
|
||||||
}
|
|
||||||
println!("Result: {:?}", result);
|
println!("Result: {:?}", result);
|
||||||
println!("Instruction Count: {}", vm.get_total_instruction_count());
|
println!("Instruction Count: {}", vm.get_total_instruction_count());
|
||||||
println!("Execution time: {} us", duration.whole_microseconds());
|
println!("Execution time: {} us", duration.whole_microseconds());
|
||||||
|
|
|
@ -47,8 +47,6 @@ use crate::{
|
||||||
cost_tracker::CostTracker,
|
cost_tracker::CostTracker,
|
||||||
epoch_stakes::{EpochStakes, NodeVoteAccounts},
|
epoch_stakes::{EpochStakes, NodeVoteAccounts},
|
||||||
inline_spl_token_v2_0,
|
inline_spl_token_v2_0,
|
||||||
instruction_recorder::InstructionRecorder,
|
|
||||||
log_collector::LogCollector,
|
|
||||||
message_processor::MessageProcessor,
|
message_processor::MessageProcessor,
|
||||||
rent_collector::RentCollector,
|
rent_collector::RentCollector,
|
||||||
stake_weighted_timestamp::{
|
stake_weighted_timestamp::{
|
||||||
|
@ -71,7 +69,11 @@ use rayon::{
|
||||||
};
|
};
|
||||||
use solana_measure::measure::Measure;
|
use solana_measure::measure::Measure;
|
||||||
use solana_metrics::{inc_new_counter_debug, inc_new_counter_info};
|
use solana_metrics::{inc_new_counter_debug, inc_new_counter_info};
|
||||||
use solana_program_runtime::{ExecuteDetailsTimings, Executors, InstructionProcessor};
|
use solana_program_runtime::{
|
||||||
|
instruction_processor::{ExecuteDetailsTimings, Executors, InstructionProcessor},
|
||||||
|
instruction_recorder::InstructionRecorder,
|
||||||
|
log_collector::LogCollector,
|
||||||
|
};
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use solana_sdk::recent_blockhashes_account;
|
use solana_sdk::recent_blockhashes_account;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
@ -3870,7 +3872,7 @@ impl Bank {
|
||||||
legacy_message,
|
legacy_message,
|
||||||
&loaded_transaction.program_indices,
|
&loaded_transaction.program_indices,
|
||||||
&account_refcells,
|
&account_refcells,
|
||||||
&self.rent_collector,
|
self.rent_collector.rent,
|
||||||
log_collector.clone(),
|
log_collector.clone(),
|
||||||
executors.clone(),
|
executors.clone(),
|
||||||
instruction_recorders.as_deref(),
|
instruction_recorders.as_deref(),
|
||||||
|
|
|
@ -32,9 +32,7 @@ pub mod genesis_utils;
|
||||||
pub mod hardened_unpack;
|
pub mod hardened_unpack;
|
||||||
pub mod in_mem_accounts_index;
|
pub mod in_mem_accounts_index;
|
||||||
pub mod inline_spl_token_v2_0;
|
pub mod inline_spl_token_v2_0;
|
||||||
pub mod instruction_recorder;
|
|
||||||
pub mod loader_utils;
|
pub mod loader_utils;
|
||||||
pub mod log_collector;
|
|
||||||
pub mod message_processor;
|
pub mod message_processor;
|
||||||
pub mod neon_evm_program;
|
pub mod neon_evm_program;
|
||||||
pub mod non_circulating_supply;
|
pub mod non_circulating_supply;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -254,15 +254,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use solana_program_runtime::invoke_context::ThisInvokeContext;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::ReadableAccount,
|
account::ReadableAccount,
|
||||||
account_utils::State as AccountUtilsState,
|
account_utils::State as AccountUtilsState,
|
||||||
hash::{hash, Hash},
|
hash::{hash, Hash},
|
||||||
keyed_account::KeyedAccount,
|
keyed_account::KeyedAccount,
|
||||||
nonce::{self, State},
|
nonce::{self, State},
|
||||||
nonce_account::create_account,
|
nonce_account::{create_account, verify_nonce_account},
|
||||||
nonce_account::verify_nonce_account,
|
|
||||||
process_instruction::MockInvokeContext,
|
|
||||||
system_instruction::SystemError,
|
system_instruction::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,11 +282,11 @@ mod test {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_invoke_context_with_blockhash<'a>(seed: usize) -> MockInvokeContext<'a> {
|
fn create_invoke_context_with_blockhash<'a>(seed: usize) -> ThisInvokeContext<'a> {
|
||||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
let mut invoke_context = ThisInvokeContext::new_mock(&[], &[]);
|
||||||
let (blockhash, lamports_per_signature) = create_test_blockhash(seed);
|
let (blockhash, lamports_per_signature) = create_test_blockhash(seed);
|
||||||
invoke_context.blockhash = blockhash;
|
invoke_context.set_blockhash(blockhash);
|
||||||
invoke_context.lamports_per_signature = lamports_per_signature;
|
invoke_context.set_lamports_per_signature(lamports_per_signature);
|
||||||
invoke_context
|
invoke_context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,12 +973,11 @@ mod test {
|
||||||
let min_lamports = rent.minimum_balance(State::size());
|
let min_lamports = rent.minimum_balance(State::size());
|
||||||
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
|
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
|
||||||
let mut signers = HashSet::new();
|
let mut signers = HashSet::new();
|
||||||
let invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
|
||||||
signers.insert(*nonce_account.signer_key().unwrap());
|
signers.insert(*nonce_account.signer_key().unwrap());
|
||||||
let result = nonce_account.authorize_nonce_account(
|
let result = nonce_account.authorize_nonce_account(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&ThisInvokeContext::new_mock(&[], &[]),
|
||||||
);
|
);
|
||||||
assert_eq!(result, Err(InstructionError::InvalidAccountData));
|
assert_eq!(result, Err(InstructionError::InvalidAccountData));
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,7 +24,7 @@ use {
|
||||||
rayon::prelude::*,
|
rayon::prelude::*,
|
||||||
serde::{de::DeserializeOwned, Deserialize, Serialize},
|
serde::{de::DeserializeOwned, Deserialize, Serialize},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_program_runtime::InstructionProcessor,
|
solana_program_runtime::instruction_processor::InstructionProcessor,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
clock::{Epoch, Slot, UnixTimestamp},
|
clock::{Epoch, Slot, UnixTimestamp},
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,15 +4,13 @@ use itertools::Itertools;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::AccountSharedData,
|
account::AccountSharedData,
|
||||||
compute_budget::ComputeBudget,
|
compute_budget::ComputeBudget,
|
||||||
feature_set::remove_native_loader,
|
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::{CompiledInstruction, Instruction, InstructionError},
|
instruction::{CompiledInstruction, Instruction, InstructionError},
|
||||||
keyed_account::{create_keyed_accounts_unified, KeyedAccount},
|
keyed_account::KeyedAccount,
|
||||||
message::Message,
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar::Sysvar,
|
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashSet, fmt::Debug, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
/// Prototype of a native loader entry point
|
/// Prototype of a native loader entry point
|
||||||
///
|
///
|
||||||
|
@ -29,32 +27,6 @@ pub type LoaderEntrypoint = unsafe extern "C" fn(
|
||||||
pub type ProcessInstructionWithContext =
|
pub type ProcessInstructionWithContext =
|
||||||
fn(usize, &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
|
fn(usize, &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
|
||||||
|
|
||||||
pub struct InvokeContextStackFrame<'a> {
|
|
||||||
pub number_of_program_accounts: usize,
|
|
||||||
pub keyed_accounts: Vec<KeyedAccount<'a>>,
|
|
||||||
pub keyed_accounts_range: std::ops::Range<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> InvokeContextStackFrame<'a> {
|
|
||||||
pub fn new(number_of_program_accounts: usize, keyed_accounts: Vec<KeyedAccount<'a>>) -> Self {
|
|
||||||
let keyed_accounts_range = std::ops::Range {
|
|
||||||
start: 0,
|
|
||||||
end: keyed_accounts.len(),
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
number_of_program_accounts,
|
|
||||||
keyed_accounts,
|
|
||||||
keyed_accounts_range,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn program_id(&self) -> Option<&Pubkey> {
|
|
||||||
self.keyed_accounts
|
|
||||||
.get(self.number_of_program_accounts.saturating_sub(1))
|
|
||||||
.map(|keyed_account| keyed_account.unsigned_key())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invocation context passed to loaders
|
/// Invocation context passed to loaders
|
||||||
pub trait InvokeContext {
|
pub trait InvokeContext {
|
||||||
/// Push a stack frame onto the invocation stack
|
/// Push a stack frame onto the invocation stack
|
||||||
|
@ -168,26 +140,6 @@ macro_rules! ic_msg {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sysvar<T: Sysvar>(
|
|
||||||
invoke_context: &dyn InvokeContext,
|
|
||||||
id: &Pubkey,
|
|
||||||
) -> Result<T, InstructionError> {
|
|
||||||
invoke_context
|
|
||||||
.get_sysvars()
|
|
||||||
.iter()
|
|
||||||
.find_map(|(key, data)| {
|
|
||||||
if id == key {
|
|
||||||
bincode::deserialize(data).ok()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ic_msg!(invoke_context, "Unable to get sysvar {}", id);
|
|
||||||
InstructionError::UnsupportedSysvar
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compute meter
|
/// Compute meter
|
||||||
pub trait ComputeMeter {
|
pub trait ComputeMeter {
|
||||||
/// Consume compute units
|
/// Consume compute units
|
||||||
|
@ -318,202 +270,3 @@ pub trait Executor: Debug + Send + Sync {
|
||||||
use_jit: bool,
|
use_jit: bool,
|
||||||
) -> Result<(), InstructionError>;
|
) -> Result<(), InstructionError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct MockComputeMeter {
|
|
||||||
pub remaining: u64,
|
|
||||||
}
|
|
||||||
impl ComputeMeter for MockComputeMeter {
|
|
||||||
fn consume(&mut self, amount: u64) -> Result<(), InstructionError> {
|
|
||||||
let exceeded = self.remaining < amount;
|
|
||||||
self.remaining = self.remaining.saturating_sub(amount);
|
|
||||||
if exceeded {
|
|
||||||
return Err(InstructionError::ComputationalBudgetExceeded);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_remaining(&self) -> u64 {
|
|
||||||
self.remaining
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct MockLogger {
|
|
||||||
pub log: Rc<RefCell<Vec<String>>>,
|
|
||||||
}
|
|
||||||
impl Logger for MockLogger {
|
|
||||||
fn log_enabled(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
fn log(&self, message: &str) {
|
|
||||||
self.log.borrow_mut().push(message.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub struct MockInvokeContext<'a> {
|
|
||||||
pub invoke_stack: Vec<InvokeContextStackFrame<'a>>,
|
|
||||||
pub logger: MockLogger,
|
|
||||||
pub compute_budget: ComputeBudget,
|
|
||||||
pub compute_meter: Rc<RefCell<dyn ComputeMeter>>,
|
|
||||||
pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>,
|
|
||||||
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
|
|
||||||
pub sysvars: &'a [(Pubkey, Vec<u8>)],
|
|
||||||
pub disabled_features: HashSet<Pubkey>,
|
|
||||||
pub blockhash: Hash,
|
|
||||||
pub lamports_per_signature: u64,
|
|
||||||
pub return_data: (Pubkey, Vec<u8>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> MockInvokeContext<'a> {
|
|
||||||
pub fn new(program_id: &Pubkey, keyed_accounts: Vec<KeyedAccount<'a>>) -> Self {
|
|
||||||
let compute_budget = ComputeBudget::default();
|
|
||||||
let mut invoke_context = MockInvokeContext {
|
|
||||||
invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth),
|
|
||||||
logger: MockLogger::default(),
|
|
||||||
compute_budget,
|
|
||||||
compute_meter: Rc::new(RefCell::new(MockComputeMeter {
|
|
||||||
remaining: std::i64::MAX as u64,
|
|
||||||
})),
|
|
||||||
programs: vec![],
|
|
||||||
accounts: vec![],
|
|
||||||
sysvars: &[],
|
|
||||||
disabled_features: HashSet::default(),
|
|
||||||
blockhash: Hash::default(),
|
|
||||||
lamports_per_signature: 0,
|
|
||||||
return_data: (Pubkey::default(), Vec::new()),
|
|
||||||
};
|
|
||||||
let number_of_program_accounts = keyed_accounts
|
|
||||||
.iter()
|
|
||||||
.position(|keyed_account| keyed_account.unsigned_key() == program_id)
|
|
||||||
.unwrap_or(0)
|
|
||||||
.saturating_add(1);
|
|
||||||
invoke_context
|
|
||||||
.invoke_stack
|
|
||||||
.push(InvokeContextStackFrame::new(
|
|
||||||
number_of_program_accounts,
|
|
||||||
keyed_accounts,
|
|
||||||
));
|
|
||||||
invoke_context
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> InvokeContext for MockInvokeContext<'a> {
|
|
||||||
fn push(
|
|
||||||
&mut self,
|
|
||||||
_message: &Message,
|
|
||||||
_instruction: &CompiledInstruction,
|
|
||||||
_program_indices: &[usize],
|
|
||||||
_account_indices: Option<&[usize]>,
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
self.invoke_stack.push(InvokeContextStackFrame::new(
|
|
||||||
0,
|
|
||||||
create_keyed_accounts_unified(&[]),
|
|
||||||
));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn pop(&mut self) {
|
|
||||||
self.invoke_stack.pop();
|
|
||||||
}
|
|
||||||
fn invoke_depth(&self) -> usize {
|
|
||||||
self.invoke_stack.len()
|
|
||||||
}
|
|
||||||
fn verify(
|
|
||||||
&mut self,
|
|
||||||
_message: &Message,
|
|
||||||
_instruction: &CompiledInstruction,
|
|
||||||
_program_indices: &[usize],
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn verify_and_update(
|
|
||||||
&mut self,
|
|
||||||
_instruction: &CompiledInstruction,
|
|
||||||
_account_indices: &[usize],
|
|
||||||
_write_pivileges: &[bool],
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
|
|
||||||
self.invoke_stack
|
|
||||||
.last()
|
|
||||||
.and_then(|frame| frame.program_id())
|
|
||||||
.ok_or(InstructionError::CallDepth)
|
|
||||||
}
|
|
||||||
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
|
|
||||||
if !self.is_feature_active(&remove_native_loader::id()) {
|
|
||||||
let stack_frame = &mut self
|
|
||||||
.invoke_stack
|
|
||||||
.last_mut()
|
|
||||||
.ok_or(InstructionError::CallDepth)?;
|
|
||||||
stack_frame.keyed_accounts_range.start =
|
|
||||||
stack_frame.keyed_accounts_range.start.saturating_add(1);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_keyed_accounts(&self) -> Result<&[KeyedAccount], InstructionError> {
|
|
||||||
self.invoke_stack
|
|
||||||
.last()
|
|
||||||
.map(|frame| &frame.keyed_accounts[frame.keyed_accounts_range.clone()])
|
|
||||||
.ok_or(InstructionError::CallDepth)
|
|
||||||
}
|
|
||||||
fn get_programs(&self) -> &[(Pubkey, ProcessInstructionWithContext)] {
|
|
||||||
&self.programs
|
|
||||||
}
|
|
||||||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
|
|
||||||
Rc::new(RefCell::new(self.logger.clone()))
|
|
||||||
}
|
|
||||||
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
|
|
||||||
self.compute_meter.clone()
|
|
||||||
}
|
|
||||||
fn add_executor(&self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
|
|
||||||
fn get_executor(&self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn set_instruction_index(&mut self, _instruction_index: usize) {}
|
|
||||||
fn record_instruction(&self, _instruction: &Instruction) {}
|
|
||||||
fn is_feature_active(&self, feature_id: &Pubkey) -> bool {
|
|
||||||
!self.disabled_features.contains(feature_id)
|
|
||||||
}
|
|
||||||
fn get_account(&self, pubkey: &Pubkey) -> Option<(usize, Rc<RefCell<AccountSharedData>>)> {
|
|
||||||
for (index, (key, account)) in self.accounts.iter().enumerate().rev() {
|
|
||||||
if key == pubkey {
|
|
||||||
return Some((index, account.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn update_timing(
|
|
||||||
&mut self,
|
|
||||||
_serialize_us: u64,
|
|
||||||
_create_vm_us: u64,
|
|
||||||
_execute_us: u64,
|
|
||||||
_deserialize_us: u64,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
fn get_sysvars(&self) -> &[(Pubkey, Vec<u8>)] {
|
|
||||||
self.sysvars
|
|
||||||
}
|
|
||||||
fn get_compute_budget(&self) -> &ComputeBudget {
|
|
||||||
&self.compute_budget
|
|
||||||
}
|
|
||||||
fn set_blockhash(&mut self, hash: Hash) {
|
|
||||||
self.blockhash = hash;
|
|
||||||
}
|
|
||||||
fn get_blockhash(&self) -> &Hash {
|
|
||||||
&self.blockhash
|
|
||||||
}
|
|
||||||
fn set_lamports_per_signature(&mut self, lamports_per_signature: u64) {
|
|
||||||
self.lamports_per_signature = lamports_per_signature;
|
|
||||||
}
|
|
||||||
fn get_lamports_per_signature(&self) -> u64 {
|
|
||||||
self.lamports_per_signature
|
|
||||||
}
|
|
||||||
fn set_return_data(&mut self, data: Vec<u8>) -> Result<(), InstructionError> {
|
|
||||||
self.return_data = (*self.get_caller()?, data);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_return_data(&self) -> (Pubkey, &[u8]) {
|
|
||||||
(self.return_data.0, &self.return_data.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue