Updating programs and loading all program related accounts
This commit is contained in:
parent
ce43a5e338
commit
cf291318b9
|
@ -5955,6 +5955,7 @@ dependencies = [
|
|||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with 2.3.3",
|
||||
"sha2 0.10.8",
|
||||
"solana-account-decoder",
|
||||
"solana-client",
|
||||
"solana-sdk",
|
||||
|
@ -6758,11 +6759,13 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"autobahn-executor",
|
||||
"base64 0.12.3",
|
||||
"bincode",
|
||||
"bonfida-test-utils",
|
||||
"env_logger",
|
||||
"log 0.4.21",
|
||||
"router-test-lib",
|
||||
"sha2 0.10.8",
|
||||
"solana-address-lookup-table-program",
|
||||
"solana-program",
|
||||
"solana-program-test",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use jupiter_amm_interface::{Amm, QuoteParams, SwapMode};
|
||||
|
@ -106,6 +107,7 @@ impl DexInterface for InfinityDex {
|
|||
|
||||
fn program_ids(&self) -> HashSet<Pubkey> {
|
||||
[
|
||||
Pubkey::from_str("5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx").unwrap(),
|
||||
s_controller_lib::program::ID,
|
||||
sanctum_spl_multi_stake_pool_program::ID,
|
||||
sanctum_spl_stake_pool_program::ID,
|
||||
|
|
|
@ -32,3 +32,4 @@ lz4 = "1.25.0"
|
|||
async-channel = "1.9.0"
|
||||
lazy_static = "1.5.0"
|
||||
anchor-spl = { version = "0.29.0", features = ["associated_token"] }
|
||||
sha2 = "0.10.8"
|
||||
|
|
|
@ -8,15 +8,19 @@ use itertools::Itertools;
|
|||
use mango_feeds_connector::chain_data::AccountData;
|
||||
use router_feed_lib::router_rpc_client::{RouterRpcClient, RouterRpcClientTrait};
|
||||
use router_test_lib::{execution_dump, serialize};
|
||||
use serde::Deserialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
use solana_sdk::account::ReadableAccount;
|
||||
use solana_sdk::clock::Clock;
|
||||
use solana_sdk::config::program;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Keypair;
|
||||
use solana_sdk::signer::Signer;
|
||||
use solana_sdk::sysvar::SysvarId;
|
||||
use std::collections::HashSet;
|
||||
use solana_sdk::bpf_loader_upgradeable::UpgradeableLoaderState;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, error};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub async fn run_dump_mainnet_data(
|
||||
dex: Arc<dyn DexInterface>,
|
||||
|
@ -67,7 +71,7 @@ pub async fn run_dump_mainnet_data_with_custom_amount(
|
|||
let mut skipped = 0;
|
||||
let mut success = 0;
|
||||
|
||||
let mut accounts_needed = HashSet::new();
|
||||
let mut accounts_needed = dex.program_ids();
|
||||
for id in edges_identifiers {
|
||||
accounts_needed.insert(id.input_mint());
|
||||
accounts_needed.insert(id.output_mint());
|
||||
|
@ -123,7 +127,17 @@ pub async fn run_dump_mainnet_data_with_custom_amount(
|
|||
for x in accounts_needed.iter().take(10) {
|
||||
println!("- {} ", x);
|
||||
}
|
||||
rpc_client.get_multiple_accounts(&accounts_needed).await?;
|
||||
let accounts = rpc_client.get_multiple_accounts(&accounts_needed).await?;
|
||||
|
||||
for (_, account) in accounts {
|
||||
// get buffer for upgradable programs
|
||||
if account.owner == solana_sdk::bpf_loader_upgradeable::ID {
|
||||
let state = bincode::deserialize::<UpgradeableLoaderState>(&account.data).unwrap();
|
||||
if let UpgradeableLoaderState::Program { programdata_address } = state {
|
||||
rpc_client.get_account(&programdata_address).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Error count: {}", errors);
|
||||
println!("Skipped count: {}", skipped);
|
||||
|
@ -312,6 +326,31 @@ pub async fn run_dump_swap_ix_with_custom_amount(
|
|||
println!("Success count: {}", success);
|
||||
println!("Exactout Success count: {}", exact_out_sucess);
|
||||
|
||||
for program in dump.programs.clone() {
|
||||
let program_account = account_provider.account(&program)?;
|
||||
|
||||
dump.accounts.insert(program, program_account.account.clone());
|
||||
// use downloaded buffers for the upgradable programs
|
||||
if *program_account.account.owner() == solana_sdk::bpf_loader_upgradeable::ID {
|
||||
let state = bincode::deserialize::<UpgradeableLoaderState>(program_account.account.data()).unwrap();
|
||||
if let UpgradeableLoaderState::Program { programdata_address } = state {
|
||||
let program_data_account = account_provider.account(&programdata_address)?;
|
||||
dump.accounts.insert(programdata_address, program_data_account.account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for program in &dump.programs {
|
||||
debug!("program : {program:?}");
|
||||
}
|
||||
|
||||
for (pk, program) in &dump.accounts {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(program.data());
|
||||
let result = hasher.finalize();
|
||||
let base64 = base64::encode(result);
|
||||
debug!("account : {pk:?} dump : {base64:?}");
|
||||
}
|
||||
serialize::serialize_to_file(
|
||||
&dump,
|
||||
&format!("../../programs/simulator/tests/fixtures/{}", dump_name).to_string(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::account::AccountSharedData;
|
||||
|
@ -17,7 +17,7 @@ pub struct ExecutionItem {
|
|||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionDump {
|
||||
pub wallet_keypair: String,
|
||||
pub programs: Vec<Pubkey>,
|
||||
pub programs: HashSet<Pubkey>,
|
||||
pub cache: Vec<ExecutionItem>,
|
||||
pub accounts: HashMap<Pubkey, AccountSharedData>,
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ use spl_token_2022::state::AccountState as AccountState2022;
|
|||
use std::collections::HashMap;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
// use sha2::Sha256;
|
||||
// use sha2::Digest;
|
||||
|
||||
struct TestLogSyscallStubs;
|
||||
impl SyscallStubs for TestLogSyscallStubs {
|
||||
|
@ -121,16 +123,18 @@ async fn run_all_swap_from_dump(dump_name: &str) -> Result<Result<(), Error>, Er
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut ctx = setup_test_chain(&data.programs, &clock).await;
|
||||
let instruction = deserialize_instruction("e.instruction)?;
|
||||
|
||||
let programs = data.programs.iter().copied().collect();
|
||||
let mut ctx = setup_test_chain(&programs, &clock, &data).await;
|
||||
|
||||
create_wallet(&mut ctx, wallet.pubkey());
|
||||
|
||||
let initial_in_balance = quote.input_amount * 2;
|
||||
let initial_out_balance = 1_000_000;
|
||||
|
||||
let instruction = deserialize_instruction("e.instruction)?;
|
||||
|
||||
initialize_instruction_accounts(&mut ctx, &data, &instruction).await?;
|
||||
// let slot = ctx.banks_client.get_root_slot().await.unwrap();
|
||||
// ctx.warp_to_slot(slot+3).unwrap();
|
||||
|
||||
let input_mint_is_2022 = is_2022(&data.accounts, quote.input_mint).await;
|
||||
let output_mint_is_2022 = is_2022(&data.accounts, quote.output_mint).await;
|
||||
|
@ -152,6 +156,20 @@ async fn run_all_swap_from_dump(dump_name: &str) -> Result<Result<(), Error>, Er
|
|||
)
|
||||
.await?;
|
||||
|
||||
for meta in &instruction.accounts {
|
||||
let Ok(Some(account)) = ctx.banks_client.get_account(meta.pubkey).await else {
|
||||
log::warn!("missing account : {:?}", meta.pubkey);
|
||||
continue;
|
||||
};
|
||||
// keep code to test hashses
|
||||
// let mut hasher = Sha256::new();
|
||||
// hasher.update(account.data());
|
||||
// let result = hasher.finalize();
|
||||
// let base64 = base64::encode(result);
|
||||
// log::debug!("account : {:?} dump : {base64:?} executable : {}", meta.pubkey, account.executable());
|
||||
}
|
||||
|
||||
|
||||
if let Some(cus) = simulate_cu_usage(&mut ctx, &wallet, &instruction).await {
|
||||
cus_required.push(cus);
|
||||
}
|
||||
|
@ -324,31 +342,21 @@ fn deserialize_instruction(swap_ix: &Vec<u8>) -> anyhow::Result<Instruction> {
|
|||
Ok(instruction)
|
||||
}
|
||||
|
||||
async fn initialize_instruction_accounts(
|
||||
ctx: &mut ProgramTestContext,
|
||||
async fn initialize_accounts(
|
||||
program_test: &mut ProgramTest,
|
||||
dump: &ExecutionDump,
|
||||
instruction: &Instruction,
|
||||
) -> anyhow::Result<()> {
|
||||
for account_meta in &instruction.accounts {
|
||||
if dump.programs.contains(&account_meta.pubkey) {
|
||||
continue;
|
||||
}
|
||||
if let Some(account) = dump.accounts.get(&account_meta.pubkey) {
|
||||
if account.executable() {
|
||||
continue;
|
||||
}
|
||||
debug!("Setting data for {}", account_meta.pubkey);
|
||||
ctx.set_account(&account_meta.pubkey, account);
|
||||
} else {
|
||||
if ctx
|
||||
.banks_client
|
||||
.get_account(account_meta.pubkey)
|
||||
.await?
|
||||
.is_none()
|
||||
{
|
||||
debug!("Missing data for {}", account_meta.pubkey); // Can happen for empty oracle account...
|
||||
}
|
||||
}
|
||||
|
||||
println!("initializing accounts : {:?}", dump.accounts.len() );
|
||||
for (pk, account) in &dump.accounts {
|
||||
println!("Setting data for {}", pk);
|
||||
program_test.add_account(*pk, solana_sdk::account::Account {
|
||||
lamports: account.lamports(),
|
||||
owner: *account.owner(),
|
||||
data: account.data().to_vec(),
|
||||
rent_epoch: account.rent_epoch(),
|
||||
executable: account.executable(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -518,7 +526,9 @@ fn create_wallet(ctx: &mut ProgramTestContext, address: Pubkey) {
|
|||
);
|
||||
}
|
||||
|
||||
async fn setup_test_chain(programs: &Vec<Pubkey>, clock: &Clock) -> ProgramTestContext {
|
||||
async fn setup_test_chain(programs: &Vec<Pubkey>, clock: &Clock,
|
||||
dump: &ExecutionDump,
|
||||
) -> ProgramTestContext {
|
||||
// We need to intercept logs to capture program log output
|
||||
let log_filter = "solana_rbpf=trace,\
|
||||
solana_runtime::message_processor=debug,\
|
||||
|
@ -534,20 +544,26 @@ async fn setup_test_chain(programs: &Vec<Pubkey>, clock: &Clock) -> ProgramTestC
|
|||
let _ = log::set_boxed_logger(Box::new(env_logger));
|
||||
|
||||
let mut program_test = ProgramTest::default();
|
||||
|
||||
initialize_accounts(&mut program_test, dump).await.unwrap();
|
||||
|
||||
program_test.prefer_bpf(true);
|
||||
for &key in programs {
|
||||
program_test.add_program(key.to_string().as_str(), key, None);
|
||||
}
|
||||
program_test.add_program("autobahn_executor", autobahn_executor::ID, None);
|
||||
|
||||
|
||||
// TODO: make this dynamic based on routes
|
||||
program_test.set_compute_max_units(1_400_000);
|
||||
|
||||
let program_test_context = program_test.start_with_context().await;
|
||||
let mut program_test_context = program_test.start_with_context().await;
|
||||
|
||||
// Set clock
|
||||
program_test_context.set_sysvar(clock);
|
||||
|
||||
info!("Setting clock to: {}", clock.unix_timestamp);
|
||||
|
||||
program_test_context.warp_to_slot(40).unwrap();
|
||||
|
||||
program_test_context
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
for filename in programs/simulator/tests/fixtures/*.so; do
|
||||
filename=$(basename $filename)
|
||||
filename="${filename%.*}"
|
||||
echo $filename
|
||||
solana program dump -um $filename $SOURCE/$filename.so
|
||||
done
|
Binary file not shown.
Loading…
Reference in New Issue