adding identity, adding bootcode for keeper

This commit is contained in:
Godmode Galactus 2023-02-21 09:49:20 +01:00
parent 70af47d9fe
commit 31cbd96897
No known key found for this signature in database
GPG Key ID: A04142C71ABB0DEA
11 changed files with 169 additions and 46 deletions

View File

@ -8,6 +8,8 @@ license = "Apache-2.0"
homepage = "https://solana.com/" homepage = "https://solana.com/"
publish = false publish = false
rust-version = "1.66.1"
[dependencies] [dependencies]
borsh = "0.9.3" borsh = "0.9.3"
chrono = "0.4.19" chrono = "0.4.19"

1
deps/mango-v3 vendored

@ -1 +0,0 @@
Subproject commit 771cabea1cb848439d282e43bf5f0e20ef7c9703

1
deps/solana vendored

@ -1 +0,0 @@
Subproject commit 030eb5f2caadebeb5d656c1a0b2d2058ea4bd242

View File

@ -23,6 +23,7 @@ pub struct Config {
pub mango_cluster: String, pub mango_cluster: String,
pub txs_batch_size: Option<usize>, pub txs_batch_size: Option<usize>,
pub priority_fees_proba: u8, pub priority_fees_proba: u8,
pub authority: Keypair,
} }
impl Default for Config { impl Default for Config {
@ -41,6 +42,7 @@ impl Default for Config {
mango_cluster: "testnet.0".to_string(), mango_cluster: "testnet.0".to_string(),
txs_batch_size: None, txs_batch_size: None,
priority_fees_proba: 0, priority_fees_proba: 0,
authority: Keypair::new(),
} }
} }
} }
@ -180,7 +182,18 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
.validator(is_valid_percentage) .validator(is_valid_percentage)
.takes_value(true) .takes_value(true)
.required(false) .required(false)
.help("Takes percentage of transaction we want to add random prioritization fees to, prioritization fees are random number between 100-1000"), .help("Takes percentage of transaction we want to add random prioritization fees to, prioritization fees are random number between 100-1000")
)
.arg(
Arg::with_name("keeper-authority")
.long("keeper-authority")
.short("ka")
.value_name("STR")
.takes_value(true)
.required(false)
.help(
"If specified, authority keypair would be used to pay for keeper transactions",
),
) )
} }
@ -262,5 +275,15 @@ pub fn extract_args(matches: &ArgMatches) -> Config {
Some(x) => x.parse().expect("Percentage of transactions having prioritization fees"), Some(x) => x.parse().expect("Percentage of transactions having prioritization fees"),
None => 0, None => 0,
}; };
let (_, kp_auth_path) = ConfigInput::compute_keypair_path_setting(
matches.value_of("keeper-authority").unwrap_or(""),
&config.keypair_path,
);
if let Ok(kpa) = read_keypair_file(kp_auth_path) {
args.authority = kpa;
} else if matches.is_present("identity") {
panic!("could not parse identity path");
}
args args
} }

View File

@ -23,7 +23,6 @@ use solana_transaction_status::RewardType;
use crate::{ use crate::{
helpers::seconds_since, helpers::seconds_since,
rotating_queue::RotatingQueue,
states::{BlockData, TransactionConfirmRecord, TransactionSendRecord}, states::{BlockData, TransactionConfirmRecord, TransactionSendRecord},
}; };
@ -201,7 +200,7 @@ pub fn confirmation_by_querying_rpc(
} }
pub fn confirmations_by_blocks( pub fn confirmations_by_blocks(
clients: RotatingQueue<Arc<RpcClient>>, client: Arc<RpcClient>,
current_slot: &AtomicU64, current_slot: &AtomicU64,
recv_limit: usize, recv_limit: usize,
tx_record_rx: Receiver<TransactionSendRecord>, tx_record_rx: Receiver<TransactionSendRecord>,
@ -245,8 +244,7 @@ pub fn confirmations_by_blocks(
let commitment_confirmation = CommitmentConfig { let commitment_confirmation = CommitmentConfig {
commitment: CommitmentLevel::Confirmed, commitment: CommitmentLevel::Confirmed,
}; };
let block_res = clients let block_res = client
.get()
.get_blocks_with_commitment(last_slot, None, commitment_confirmation) .get_blocks_with_commitment(last_slot, None, commitment_confirmation)
.unwrap(); .unwrap();
@ -264,7 +262,7 @@ pub fn confirmations_by_blocks(
.map(|x| x.to_vec()) .map(|x| x.to_vec())
{ {
let map = transaction_map.clone(); let map = transaction_map.clone();
let client = clients.get().clone(); let client = client.clone();
let tx_confirm_records = tx_confirm_records.clone(); let tx_confirm_records = tx_confirm_records.clone();
let tx_block_data = tx_block_data.clone(); let tx_block_data = tx_block_data.clone();
let joinble = Builder::new() let joinble = Builder::new()

View File

@ -245,6 +245,13 @@ pub fn get_mango_market_perps_cache(
.div(I80F48::from_num(perp_market.base_lot_size)) .div(I80F48::from_num(perp_market.base_lot_size))
.to_num(); .to_num();
let root_bank = &mango_group_config.tokens[market_index].root_key;
let root_bank = Pubkey::from_str(root_bank.as_str()).unwrap();
let node_banks = mango_group_config.tokens[market_index]
.node_keys
.iter()
.map(|x| Pubkey::from_str(x.as_str()).unwrap())
.collect();
PerpMarketCache { PerpMarketCache {
order_base_lots, order_base_lots,
price, price,
@ -254,6 +261,8 @@ pub fn get_mango_market_perps_cache(
mango_cache_pk, mango_cache_pk,
perp_market_pk, perp_market_pk,
perp_market, perp_market,
root_bank,
node_banks,
} }
}) })
.collect() .collect()

104
src/keeper.rs Normal file
View File

@ -0,0 +1,104 @@
use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
},
thread::{Builder, JoinHandle},
};
use solana_client::tpu_client::TpuClient;
use solana_quic_client::{QuicConfig, QuicConnectionManager, QuicPool};
use solana_sdk::{
compute_budget::ComputeBudgetInstruction, hash::Hash, instruction::Instruction,
message::Message, signature::Keypair, signer::Signer, transaction::Transaction,
};
use crate::{helpers::to_sdk_instruction, states::PerpMarketCache};
fn create_root_bank_update_instructions(perp_markets: &Vec<PerpMarketCache>) -> Vec<Instruction> {
perp_markets
.iter()
.map(|perp_market| {
let ix = mango::instruction::update_root_bank(
&perp_market.mango_program_pk,
&perp_market.mango_group_pk,
&perp_market.mango_cache_pk,
&perp_market.root_bank,
perp_market.node_banks.as_slice(),
)
.unwrap();
to_sdk_instruction(ix)
})
.collect()
}
fn create_update_price_cache_instructions(perp_markets: &Vec<PerpMarketCache>) -> Vec<Instruction> {
perp_markets
.iter()
.map(|perp_market| {
let ix = mango::instruction::cache_prices(
&perp_market.mango_program_pk,
&perp_market.mango_group_pk,
&perp_market.mango_cache_pk,
perp_market.node_banks.as_slice(),
)
.unwrap();
to_sdk_instruction(ix)
})
.collect()
}
pub fn send_transaction(
tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
ixs: &[Instruction],
blockhash: Arc<RwLock<Hash>>,
payer: &Keypair,
) {
let mut tx = Transaction::new_unsigned(Message::new(ixs, Some(&payer.pubkey())));
if let Ok(recent_blockhash) = blockhash.read() {
tx.sign(&[payer], *recent_blockhash);
}
tpu_client.send_transaction(&tx);
}
pub fn start_root_bank_keeper(
exit_signal: Arc<AtomicBool>,
tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
perp_markets: Vec<PerpMarketCache>,
blockhash: Arc<RwLock<Hash>>,
authority: &Keypair,
) -> JoinHandle<()> {
let authority = Keypair::from_bytes(&authority.to_bytes()).unwrap();
Builder::new()
.name("updating root bank keeper".to_string())
.spawn(move || {
let tpu_client = tpu_client.clone();
let mut root_update_ixs = create_root_bank_update_instructions(&perp_markets);
let mut cache_price = create_update_price_cache_instructions(&perp_markets);
let blockhash = blockhash.clone();
// add prioritization instruction
let prioritization_ix = ComputeBudgetInstruction::set_compute_unit_price(100);
root_update_ixs.insert(0, prioritization_ix.clone());
cache_price.insert(0, prioritization_ix);
loop {
if exit_signal.load(Ordering::Relaxed) {
break;
}
send_transaction(
tpu_client.clone(),
root_update_ixs.as_slice(),
blockhash.clone(),
&authority,
);
send_transaction(
tpu_client.clone(),
cache_price.as_slice(),
blockhash.clone(),
&authority,
);
}
})
.unwrap()
}

View File

@ -1,6 +1,7 @@
pub mod cli; pub mod cli;
pub mod confirmation_strategies; pub mod confirmation_strategies;
pub mod helpers; pub mod helpers;
pub mod keeper;
pub mod mango; pub mod mango;
pub mod market_markers; pub mod market_markers;
pub mod rotating_queue; pub mod rotating_queue;

View File

@ -9,13 +9,11 @@ use solana_bench_mango::{
}, },
mango::{AccountKeys, MangoConfig}, mango::{AccountKeys, MangoConfig},
market_markers::start_market_making_threads, market_markers::start_market_making_threads,
rotating_queue::RotatingQueue,
states::{BlockData, PerpMarketCache, TransactionConfirmRecord, TransactionSendRecord}, states::{BlockData, PerpMarketCache, TransactionConfirmRecord, TransactionSendRecord},
}; };
use solana_client::{ use solana_client::{
connection_cache::ConnectionCache, rpc_client::RpcClient, tpu_client::TpuClient, connection_cache::ConnectionCache, rpc_client::RpcClient, tpu_client::TpuClient,
}; };
use solana_quic_client::{QuicConfig, QuicConnectionManager, QuicPool};
use solana_sdk::commitment_config::CommitmentConfig; use solana_sdk::commitment_config::CommitmentConfig;
use std::{ use std::{
@ -54,7 +52,10 @@ fn main() {
let transaction_save_file = transaction_save_file.clone(); let transaction_save_file = transaction_save_file.clone();
let block_data_save_file = block_data_save_file.clone(); let block_data_save_file = block_data_save_file.clone();
info!("Connecting to the cluster"); info!(
"Connecting to the cluster {}, {}",
json_rpc_url, websocket_url
);
let account_keys_json = fs::read_to_string(account_keys).expect("unable to read accounts file"); let account_keys_json = fs::read_to_string(account_keys).expect("unable to read accounts file");
let account_keys_parsed: Vec<AccountKeys> = let account_keys_parsed: Vec<AccountKeys> =
@ -71,13 +72,10 @@ fn main() {
.find(|g| g.name == *mango_group_id) .find(|g| g.name == *mango_group_id)
.unwrap(); .unwrap();
let number_of_tpu_clients: usize = 1; let rpc_client = Arc::new(RpcClient::new_with_commitment(
let rpc_clients = RotatingQueue::<Arc<RpcClient>>::new(number_of_tpu_clients, || {
Arc::new(RpcClient::new_with_commitment(
json_rpc_url.to_string(), json_rpc_url.to_string(),
CommitmentConfig::confirmed(), CommitmentConfig::confirmed(),
)) ));
});
let connection_cache = ConnectionCache::new_with_client_options( let connection_cache = ConnectionCache::new_with_client_options(
4, 4,
@ -91,20 +89,15 @@ fn main() {
None None
}; };
let tpu_client_pool = Arc::new(RotatingQueue::< let tpu_client = Arc::new(
Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
>::new(number_of_tpu_clients, || {
let quic_connection_cache = quic_connection_cache.clone();
Arc::new(
TpuClient::new_with_connection_cache( TpuClient::new_with_connection_cache(
rpc_clients.get().clone(), rpc_client.clone(),
&websocket_url, &websocket_url,
solana_client::tpu_client::TpuClientConfig::default(), solana_client::tpu_client::TpuClientConfig::default(),
quic_connection_cache.unwrap(), quic_connection_cache.unwrap(),
) )
.unwrap(), .unwrap(),
) );
}));
info!( info!(
"accounts:{:?} markets:{:?} quotes_per_second:{:?} expected_tps:{:?} duration:{:?}", "accounts:{:?} markets:{:?} quotes_per_second:{:?} expected_tps:{:?} duration:{:?}",
@ -144,7 +137,7 @@ fn main() {
exit_signal.clone(), exit_signal.clone(),
blockhash.clone(), blockhash.clone(),
current_slot.clone(), current_slot.clone(),
tpu_client_pool.clone(), tpu_client.clone(),
&duration, &duration,
*quotes_per_second, *quotes_per_second,
*txs_batch_size, *txs_batch_size,
@ -170,7 +163,7 @@ fn main() {
//confirmation_by_querying_rpc(recv_limit, rpc_client.clone(), &tx_record_rx, tx_confirm_records.clone(), tx_timeout_records.clone()); //confirmation_by_querying_rpc(recv_limit, rpc_client.clone(), &tx_record_rx, tx_confirm_records.clone(), tx_timeout_records.clone());
confirmations_by_blocks( confirmations_by_blocks(
rpc_clients, rpc_client.clone(),
&current_slot, &current_slot,
recv_limit, recv_limit,
tx_record_rx, tx_record_rx,

View File

@ -28,7 +28,6 @@ use solana_sdk::{
use crate::{ use crate::{
helpers::{to_sdk_instruction, to_sp_pk}, helpers::{to_sdk_instruction, to_sp_pk},
mango::AccountKeys, mango::AccountKeys,
rotating_queue::RotatingQueue,
states::{PerpMarketCache, TransactionSendRecord}, states::{PerpMarketCache, TransactionSendRecord},
}; };
@ -153,9 +152,7 @@ pub fn send_mm_transactions(
quotes_per_second: u64, quotes_per_second: u64,
perp_market_caches: &Vec<PerpMarketCache>, perp_market_caches: &Vec<PerpMarketCache>,
tx_record_sx: &Sender<TransactionSendRecord>, tx_record_sx: &Sender<TransactionSendRecord>,
tpu_client_pool: Arc< tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
RotatingQueue<Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>>,
>,
mango_account_pk: Pubkey, mango_account_pk: Pubkey,
mango_account_signer: &Keypair, mango_account_signer: &Keypair,
blockhash: Arc<RwLock<Hash>>, blockhash: Arc<RwLock<Hash>>,
@ -178,7 +175,7 @@ pub fn send_mm_transactions(
if let Ok(recent_blockhash) = blockhash.read() { if let Ok(recent_blockhash) = blockhash.read() {
tx.sign(&[mango_account_signer], *recent_blockhash); tx.sign(&[mango_account_signer], *recent_blockhash);
} }
let tpu_client = tpu_client_pool.get(); let tpu_client = tpu_client.clone();
tpu_client.send_transaction(&tx); tpu_client.send_transaction(&tx);
let sent = tx_record_sx.send(TransactionSendRecord { let sent = tx_record_sx.send(TransactionSendRecord {
signature: tx.signatures[0], signature: tx.signatures[0],
@ -203,9 +200,7 @@ pub fn send_mm_transactions_batched(
quotes_per_second: u64, quotes_per_second: u64,
perp_market_caches: &Vec<PerpMarketCache>, perp_market_caches: &Vec<PerpMarketCache>,
tx_record_sx: &Sender<TransactionSendRecord>, tx_record_sx: &Sender<TransactionSendRecord>,
tpu_client_pool: Arc< tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
RotatingQueue<Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>>,
>,
mango_account_pk: Pubkey, mango_account_pk: Pubkey,
mango_account_signer: &Keypair, mango_account_signer: &Keypair,
blockhash: Arc<RwLock<Hash>>, blockhash: Arc<RwLock<Hash>>,
@ -236,7 +231,7 @@ pub fn send_mm_transactions_batched(
tx.0.sign(&[mango_account_signer], *recent_blockhash); tx.0.sign(&[mango_account_signer], *recent_blockhash);
} }
} }
let tpu_client = tpu_client_pool.get(); let tpu_client = tpu_client.clone();
if tpu_client if tpu_client
.try_send_transaction_batch( .try_send_transaction_batch(
&transactions.iter().map(|x| x.0.clone()).collect_vec().as_slice(), &transactions.iter().map(|x| x.0.clone()).collect_vec().as_slice(),
@ -275,9 +270,7 @@ pub fn start_market_making_threads(
exit_signal: Arc<AtomicBool>, exit_signal: Arc<AtomicBool>,
blockhash: Arc<RwLock<Hash>>, blockhash: Arc<RwLock<Hash>>,
current_slot: Arc<AtomicU64>, current_slot: Arc<AtomicU64>,
tpu_client_pool: Arc< tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
RotatingQueue<Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>>,
>,
duration: &Duration, duration: &Duration,
quotes_per_second: u64, quotes_per_second: u64,
txs_batch_size: Option<usize>, txs_batch_size: Option<usize>,
@ -288,7 +281,7 @@ pub fn start_market_making_threads(
.map(|account_keys| { .map(|account_keys| {
let _exit_signal = exit_signal.clone(); let _exit_signal = exit_signal.clone();
// having a tpu client for each MM // having a tpu client for each MM
let tpu_client_pool = tpu_client_pool.clone(); let tpu_client_pool = tpu_client.clone();
let blockhash = blockhash.clone(); let blockhash = blockhash.clone();
let current_slot = current_slot.clone(); let current_slot = current_slot.clone();

View File

@ -43,6 +43,8 @@ pub struct PerpMarketCache {
pub mango_cache_pk: Pubkey, pub mango_cache_pk: Pubkey,
pub perp_market_pk: Pubkey, pub perp_market_pk: Pubkey,
pub perp_market: PerpMarket, pub perp_market: PerpMarket,
pub root_bank: Pubkey,
pub node_banks: Vec<Pubkey>,
} }
pub struct _TransactionInfo { pub struct _TransactionInfo {