Updating programs and loading all program related accounts

This commit is contained in:
godmodegalactus 2024-10-21 16:31:28 +02:00
parent ce43a5e338
commit cf291318b9
No known key found for this signature in database
GPG Key ID: 22DA4A30887FDA3C
10 changed files with 104 additions and 35 deletions

3
Cargo.lock generated
View File

@ -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",

View File

@ -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,

View File

@ -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"

View File

@ -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(),

View File

@ -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>,
}

View File

@ -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(&quote.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(&quote.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
}

View File

@ -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