Skip to content

Commit 6bf6406

Browse files
committed
blacklist
1 parent 6a0c081 commit 6bf6406

File tree

4 files changed

+51
-8
lines changed

4 files changed

+51
-8
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ docker-target
2424
**/keypair.json
2525
**/*.log
2626
**/.coderrect
27+
28+
admin.json

plugin/src/builders/thread_exec.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::sync::Arc;
1+
use std::collections::HashSet;
2+
use std::sync::{Arc, Mutex, RwLock};
23

34
use anchor_lang::{InstructionData, ToAccountMetas};
45
use log::info;
@@ -33,14 +34,17 @@ static TRANSACTION_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;
3334
/// The buffer amount to add to transactions' compute units in case on-chain PDA derivations take more CUs than used in simulation.
3435
static TRANSACTION_COMPUTE_UNIT_BUFFER: u32 = 1000;
3536

37+
pub const INSTRUCTION_ERROR_REENTRANCY_NOT_ALLOWED: i64 = 4615034;
38+
pub const INSTRUCTION_ERROR_ANCHOR_ACCOUNT_OWNED_BY_WRONG_PROGRAM: i64 = 3007;
39+
3640
pub async fn build_thread_exec_tx(
3741
client: Arc<RpcClient>,
3842
payer: &Keypair,
3943
slot: u64,
4044
thread: VersionedThread,
4145
thread_pubkey: Pubkey,
4246
worker_id: u64,
43-
) -> Result<Option<Transaction>, PluginError> {
47+
) -> Result<(Option<Transaction>, /* Blacklisted */ Option<Pubkey>), PluginError> {
4448
// Grab the thread and relevant data.
4549
let now = std::time::Instant::now();
4650
let blockhash = client.get_latest_blockhash().await?;
@@ -102,10 +106,25 @@ pub async fn build_thread_exec_tx(
102106
{
103107
// If there was a simulation error, stop packing and exit now.
104108
Err(err) => {
109+
// Check for specific error and blacklist the thread
105110
if let solana_client::client_error::ClientErrorKind::RpcError(
106111
solana_client::rpc_request::RpcError::RpcResponseError { code, .. },
107112
) = err.kind
108113
{
114+
if code == INSTRUCTION_ERROR_REENTRANCY_NOT_ALLOWED {
115+
info!(
116+
"INSTRUCTION_ERROR_REENTRANCY_NOT_ALLOWED, blacklisting thread: {}",
117+
thread_pubkey
118+
);
119+
return Ok((None, Some(thread_pubkey)));
120+
}
121+
if code == INSTRUCTION_ERROR_ANCHOR_ACCOUNT_OWNED_BY_WRONG_PROGRAM {
122+
info!(
123+
"INSTRUCTION_ERROR_ANCHOR_ACCOUNT_OWNED_BY_WRONG_PROGRAM, blacklisting thread: {}",
124+
thread_pubkey
125+
);
126+
return Ok((None, Some(thread_pubkey)));
127+
}
109128
if code == JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED {
110129
return Err(PluginError::MinContextSlotNotReached);
111130
}
@@ -172,7 +191,7 @@ pub async fn build_thread_exec_tx(
172191
// If there were no successful instructions, then exit early. There is nothing to do.
173192
// Alternatively, exit early if only the kickoff instruction (and no execs) succeeded.
174193
if successful_ixs.is_empty() {
175-
return Ok(None);
194+
return Ok((None, None));
176195
}
177196

178197
// Set the transaction's compute unit limit to be exactly the amount that was used in simulation.
@@ -199,7 +218,7 @@ pub async fn build_thread_exec_tx(
199218
units_consumed,
200219
tx.signatures[0]
201220
);
202-
Ok(Some(tx))
221+
Ok((Some(tx), None))
203222
}
204223

205224
fn build_kickoff_ix(

plugin/src/executors/state/executable_threads.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl ExecutableThreads {
9595
info!(
9696
"dropped_threads: {:?} executable_threads: {:?}",
9797
self.1.load(Ordering::Relaxed),
98-
*w_state
98+
*w_state,
9999
);
100100
}
101101

plugin/src/executors/tx.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::{
22
collections::{HashMap, HashSet},
33
fmt::Debug,
4-
sync::Arc,
4+
io::Write,
5+
sync::{Arc, RwLock},
56
};
67

78
use bincode::serialize;
@@ -37,6 +38,8 @@ use super::{
3738
pub struct TxExecutor {
3839
pub config: PluginConfig,
3940
pub executable_threads: ExecutableThreads,
41+
// Temporary state for blacklisted threads (from old positions that were deleted and SLTP cleanups call not working)
42+
pub blacklisted_threads: RwLock<HashSet<Pubkey>>,
4043
pub transaction_history: TransactionHistory,
4144
pub rotation_history: RotationHistory,
4245
pub keypair: Keypair,
@@ -60,6 +63,7 @@ impl TxExecutor {
6063
Self {
6164
config: config.clone(),
6265
executable_threads: ExecutableThreads::default(),
66+
blacklisted_threads: RwLock::new(HashSet::new()),
6367
transaction_history: TransactionHistory::default(),
6468
rotation_history: RotationHistory::default(),
6569
keypair: read_or_new_keypair(config.keypath),
@@ -73,6 +77,10 @@ impl TxExecutor {
7377
slot: u64,
7478
runtime: Arc<Runtime>,
7579
) -> PluginResult<()> {
80+
info!(
81+
"blacklisted_threads: {:?}",
82+
self.blacklisted_threads.read().unwrap().len()
83+
);
7684
self.executable_threads
7785
.rebase_threads(slot, &thread_pubkeys)
7886
.await;
@@ -301,7 +309,15 @@ impl TxExecutor {
301309
}
302310
}
303311

304-
if let Ok(tx) = crate::builders::build_thread_exec_tx(
312+
// check if the thread is blacklisted
313+
if self
314+
.blacklisted_threads
315+
.read()
316+
.unwrap()
317+
.contains(&thread_pubkey)
318+
{
319+
return None;
320+
} else if let Ok((tx, blacklisted)) = crate::builders::build_thread_exec_tx(
305321
client.clone(),
306322
&self.keypair,
307323
due_slot,
@@ -311,7 +327,13 @@ impl TxExecutor {
311327
)
312328
.await
313329
{
314-
if let Some(tx) = tx {
330+
if let Some(blacklisted) = blacklisted {
331+
self.blacklisted_threads
332+
.write()
333+
.unwrap()
334+
.insert(blacklisted);
335+
None
336+
} else if let Some(tx) = tx {
315337
if !self
316338
.transaction_history
317339
.is_duplicate_tx(observed_slot, thread_pubkey, &tx)

0 commit comments

Comments
 (0)