From dec6b92355cd728d94679aefa1699a47d310ade6 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 16 Aug 2024 15:37:21 -0600 Subject: [PATCH 01/28] add bloxroute v1 --- Cargo.lock | 1 + Cargo.toml | 1 + src/args.rs | 8 ++ src/main.rs | 1 + src/mine.rs | 15 +++- src/send_and_confirm_bx.rs | 149 +++++++++++++++++++++++++++++++++++++ 6 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 src/send_and_confirm_bx.rs diff --git a/Cargo.lock b/Cargo.lock index 2aeba29c..4d9227d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2774,6 +2774,7 @@ dependencies = [ name = "ore-cli" version = "2.3.0" dependencies = [ + "base64 0.22.1", "bincode", "bs58 0.5.1", "bytemuck", diff --git a/Cargo.toml b/Cargo.toml index d908dc09..5a8354c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ admin = [] [dependencies] bincode = "1.3.3" bs58 = "0.5.1" +base64 = "0.22.1" bytemuck = "1.16" cached = "0.46.1" chrono = "0.4.38" diff --git a/src/args.rs b/src/args.rs index 756aecc1..5ff0bdcd 100644 --- a/src/args.rs +++ b/src/args.rs @@ -69,6 +69,14 @@ pub struct MineArgs { default_value = "5" )] pub buffer_time: u64, + + #[arg( + long = "bxr", + value_name = "BLOXROUTE", + help = "Enable bloxroute routing", + default_value = "false" + )] + pub bloxroute: bool, } #[derive(Parser, Debug)] diff --git a/src/main.rs b/src/main.rs index 783f5286..d57c02a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod open; mod proof; mod rewards; mod send_and_confirm; +mod send_and_confirm_bx; mod stake; mod transfer; mod upgrade; diff --git a/src/mine.rs b/src/mine.rs index 5c369e3e..74e32cfd 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -82,10 +82,17 @@ impl Miner { solution, )); - // Submit transaction - self.send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) - .await - .ok(); + if args.bloxroute { + // submit transaction to bloxroute + self.send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false) + .await + .ok(); + } else { + // Submit transaction + self.send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) + .await + .ok(); + } } } diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs new file mode 100644 index 00000000..8f259abc --- /dev/null +++ b/src/send_and_confirm_bx.rs @@ -0,0 +1,149 @@ +use base64::Engine; +use chrono::Local; +use colored::Colorize; +use serde_json::json; +use solana_client::client_error::{ClientError, ClientErrorKind, Result as ClientResult}; +use solana_program::instruction::Instruction; +use solana_rpc_client::spinner; +use solana_sdk::{ + compute_budget::ComputeBudgetInstruction, signature::Signature, signer::Signer, + transaction::Transaction, +}; +use std::str::FromStr; +use std::time::Duration; + +use crate::{send_and_confirm::ComputeBudget, Miner}; + +const CONFIRM_DELAY: u64 = 500; +const CONFIRM_RETRIES: usize = 8; +const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; + +impl Miner { + pub async fn send_and_confirm_bx( + &self, + ixs: &[Instruction], + compute_budget: ComputeBudget, + skip_confirm: bool, + ) -> ClientResult { + let progress_bar = spinner::new_progress_bar(); + let signer = self.signer(); + let fee_payer = self.fee_payer(); + + // Build transaction + let mut final_ixs = vec![]; + match compute_budget { + ComputeBudget::Dynamic => { + // TODO: Implement dynamic compute budget logic + } + ComputeBudget::Fixed(cus) => { + final_ixs.push(ComputeBudgetInstruction::set_compute_unit_limit(cus)) + } + } + final_ixs.push(ComputeBudgetInstruction::set_compute_unit_price( + self.priority_fee.unwrap_or(0), + )); + final_ixs.extend_from_slice(ixs); + + let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); + let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; + + if signer.pubkey() == fee_payer.pubkey() { + tx.sign(&[&signer], recent_blockhash); + } else { + tx.sign(&[&signer, &fee_payer], recent_blockhash); + } + + // Encode transaction + let tx_data = + base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Bincode serialization error: {}", + e + ))) + })?); + + let body = json!({ + "transactions": vec![tx_data] + }); + + // Send transaction to custom endpoint + progress_bar.set_message("Submitting transaction to custom endpoint..."); + let client = reqwest::Client::new(); + let response = client + .post(BLOXROUTE_URL) + .json(&body) + .send() + .await + .map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!("Request error: {}", e))) + })?; + + let response_text = response.text().await.map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Response body error: {}", + e + ))) + })?; + + let response_json: serde_json::Value = + serde_json::from_str(&response_text).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "JSON parsing error: {}", + e + ))) + })?; + + let signature = response_json["signature"].as_str().ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "Signature not found in response".to_string(), + )) + })?; + + let signature = Signature::from_str(signature).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Signature parsing error: {}", + e + ))) + })?; + + // Skip confirmation if requested + if skip_confirm { + progress_bar.finish_with_message(format!("Sent: {}", signature)); + return Ok(signature); + } + + // Confirm transaction + progress_bar.set_message("Confirming transaction..."); + for _ in 0..CONFIRM_RETRIES { + std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); + match self.rpc_client.get_signature_status(&signature).await { + Ok(Some(status)) => { + if status.is_ok() { + let now = Local::now(); + let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); + progress_bar.println(format!(" Timestamp: {}", formatted_time)); + progress_bar.finish_with_message(format!( + "{} {}", + "OK".bold().green(), + signature + )); + return Ok(signature); + } else { + return Err(ClientError::from(ClientErrorKind::Custom(format!( + "Transaction failed: {:?}", + status + )))); + } + } + Ok(None) => continue, + Err(err) => { + progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); + } + } + } + + Err(ClientError::from(ClientErrorKind::Custom( + "Transaction confirmation timeout".into(), + ))) + } +} From 6f9430c09d86c090b4e24613353b7740f1232a67 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 16 Aug 2024 15:39:45 -0600 Subject: [PATCH 02/28] change url --- src/send_and_confirm_bx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 8f259abc..d012516c 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -16,7 +16,7 @@ use crate::{send_and_confirm::ComputeBudget, Miner}; const CONFIRM_DELAY: u64 = 500; const CONFIRM_RETRIES: usize = 8; -const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; +const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; impl Miner { pub async fn send_and_confirm_bx( From a688cc64a1c68799a56330122a5d80ebbe724264 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Mon, 19 Aug 2024 16:00:23 -0600 Subject: [PATCH 03/28] refactor --- src/main.rs | 10 +- src/mine.rs | 51 +++++- src/send_and_confirm_bx.rs | 356 ++++++++++++++++++++++++++----------- 3 files changed, 310 insertions(+), 107 deletions(-) diff --git a/src/main.rs b/src/main.rs index d57c02a8..5e70fbd7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,6 +152,14 @@ struct Args { )] jito: bool, + #[arg( + long, + value_name = "BLOXROUTE", + help = "Use Bloxroute for transaction propegation.", + global = true + )] + bloxroute: bool, + #[command(subcommand)] command: Commands, } @@ -183,7 +191,7 @@ async fn main() { let tip = Arc::new(RwLock::new(0_u64)); let tip_clone = Arc::clone(&tip); - if args.jito { + if args.jito || args.bloxroute { let url = "ws://bundles-api-rest.jito.wtf/api/v1/bundles/tip_stream"; let (ws_stream, _) = connect_async(url).await.unwrap(); let (_, mut read) = ws_stream.split(); diff --git a/src/mine.rs b/src/mine.rs index 74e32cfd..e673d829 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -26,8 +26,11 @@ use crate::{ impl Miner { pub async fn mine(&self, args: MineArgs) { + println!("Starting mining process with args: {:?}", args); + // Open account, if needed. let signer = self.signer(); + println!("Signer public key: {}", signer.pubkey()); self.open().await; // Check num threads @@ -36,12 +39,19 @@ impl Miner { // Start mining loop let mut last_hash_at = 0; let mut last_balance = 0; + let mut loop_count = 0; loop { + loop_count += 1; + println!("Starting mining loop iteration {}", loop_count); + // Fetch proof let config = get_config(&self.rpc_client).await; + println!("Fetched config: {:?}", config); let proof = get_updated_proof_with_authority(&self.rpc_client, signer.pubkey(), last_hash_at) .await; + println!("Fetched proof: {:?}", proof); + println!( "\n\nStake: {} ORE\n{} Multiplier: {:12}x", amount_u64_to_string(proof.balance), @@ -60,39 +70,68 @@ impl Miner { // Calculate cutoff time let cutoff_time = self.get_cutoff(proof, args.buffer_time).await; + println!("Calculated cutoff time: {}", cutoff_time); // Run drillx + println!("Starting hash finding process"); let solution = Self::find_hash_par(proof, cutoff_time, args.cores, config.min_difficulty as u32) .await; + println!("Found solution: {:?}", solution); // Build instruction set let mut ixs = vec![ore_api::instruction::auth(proof_pubkey(signer.pubkey()))]; let mut compute_budget = 500_000; if self.should_reset(config).await && rand::thread_rng().gen_range(0..100).eq(&0) { compute_budget += 100_000; + println!("Adding reset instruction"); ixs.push(ore_api::instruction::reset(signer.pubkey())); } // Build mine ix + println!("Finding bus"); + let bus = self.find_bus().await; + println!("Found bus: {}", bus); ixs.push(ore_api::instruction::mine( signer.pubkey(), signer.pubkey(), - self.find_bus().await, + bus, solution, )); + println!("Built {} instructions", ixs.len()); + if args.bloxroute { // submit transaction to bloxroute - self.send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false) - .await - .ok(); + println!("Submitting transaction to bloxroute"); + match self.send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false).await { + Ok(signature) => println!("Transaction submitted successfully. Signature: {}", signature), + Err(e) => { + if e.to_string().contains("Invalid hash") || e.to_string().contains("Needs reset") { + println!("Refreshing miner state due to: {}", e); + continue; + } else { + println!("Error submitting transaction: {:?}", e); + // Handle other errors as needed + } + } + } } else { // Submit transaction - self.send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) + println!("Submitting transaction to regular RPC"); + match self + .send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) .await - .ok(); + { + Ok(signature) => println!( + "Transaction submitted successfully. Signature: {}", + signature + ), + Err(e) => println!("Error submitting transaction: {:?}", e), + } } + + println!("Completed mining loop iteration {}", loop_count); } } diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index d012516c..14c5075b 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -1,22 +1,55 @@ use base64::Engine; use chrono::Local; use colored::Colorize; -use serde_json::json; +use ore_api::error::OreError; +use serde::Serialize; +use serde_json::Value; use solana_client::client_error::{ClientError, ClientErrorKind, Result as ClientResult}; -use solana_program::instruction::Instruction; +use solana_program::{ + instruction::{Instruction, InstructionError}, + pubkey::Pubkey, + system_instruction, +}; use solana_rpc_client::spinner; use solana_sdk::{ - compute_budget::ComputeBudgetInstruction, signature::Signature, signer::Signer, - transaction::Transaction, + commitment_config::CommitmentConfig, + compute_budget::ComputeBudgetInstruction, + signature::Signature, + signer::Signer, + transaction::{Transaction, TransactionError}, }; use std::str::FromStr; use std::time::Duration; use crate::{send_and_confirm::ComputeBudget, Miner}; -const CONFIRM_DELAY: u64 = 500; -const CONFIRM_RETRIES: usize = 8; +const GATEWAY_RETRIES: usize = 150; +const GATEWAY_DELAY: u64 = 0; +const CONFIRM_DELAY: u64 = 750; +const CONFIRM_RETRIES: usize = 12; const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; +const BLOXROUTE_URL_LOCAL: &str = "http://localhost:9000/api/v2/mine-ore"; + +#[derive(Serialize)] +struct TransactionMessage { + content: String, + #[serde(rename = "isCleanup")] + is_cleanup: bool, +} + +#[derive(Serialize)] +struct PostSubmitRequest { + transaction: TransactionMessage, + #[serde(rename = "skipPreFlight")] + skip_pre_flight: bool, + #[serde(rename = "frontRunningProtection")] + front_running_protection: Option, + tip: Option, + #[serde(rename = "useStakedRPCs")] + use_staked_rpcs: Option, + #[serde(rename = "fastBestEffort")] + fast_best_effort: Option, +} impl Miner { pub async fn send_and_confirm_bx( @@ -29,12 +62,10 @@ impl Miner { let signer = self.signer(); let fee_payer = self.fee_payer(); - // Build transaction + // Prepare instructions let mut final_ixs = vec![]; match compute_budget { - ComputeBudget::Dynamic => { - // TODO: Implement dynamic compute budget logic - } + ComputeBudget::Dynamic => todo!("simulate tx"), ComputeBudget::Fixed(cus) => { final_ixs.push(ComputeBudgetInstruction::set_compute_unit_limit(cus)) } @@ -42,108 +73,233 @@ impl Miner { final_ixs.push(ComputeBudgetInstruction::set_compute_unit_price( self.priority_fee.unwrap_or(0), )); + + if let Some(priority_fee) = self.priority_fee { + if priority_fee > 0 { + let tip_amount = priority_fee / 2; + let tip_pubkey = + Pubkey::from_str("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY").unwrap(); + let tip_instruction = + system_instruction::transfer(&signer.pubkey(), &tip_pubkey, tip_amount); + final_ixs.push(tip_instruction); + progress_bar.println(format!(" Additional tip: {} lamports", tip_amount)); + } else { + progress_bar.println(" No additional tip: Priority fee is zero"); + } + } + final_ixs.extend_from_slice(ixs); - let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); - let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; + let mut outer_attempts = 0; + const MAX_OUTER_ATTEMPTS: usize = 3; - if signer.pubkey() == fee_payer.pubkey() { - tx.sign(&[&signer], recent_blockhash); - } else { - tx.sign(&[&signer, &fee_payer], recent_blockhash); - } + 'outer: loop { + outer_attempts += 1; + if outer_attempts > MAX_OUTER_ATTEMPTS { + return Err(ClientError::from(ClientErrorKind::Custom( + "Max outer retries reached".into(), + ))); + } - // Encode transaction - let tx_data = - base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Bincode serialization error: {}", - e - ))) - })?); - - let body = json!({ - "transactions": vec![tx_data] - }); - - // Send transaction to custom endpoint - progress_bar.set_message("Submitting transaction to custom endpoint..."); - let client = reqwest::Client::new(); - let response = client - .post(BLOXROUTE_URL) - .json(&body) - .send() - .await - .map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!("Request error: {}", e))) - })?; + let mut attempts = 0; + let signature: Option; - let response_text = response.text().await.map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Response body error: {}", - e - ))) - })?; - - let response_json: serde_json::Value = - serde_json::from_str(&response_text).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "JSON parsing error: {}", - e - ))) - })?; + 'submission: loop { + attempts += 1; + if attempts > GATEWAY_RETRIES { + progress_bar.println("Max gateway retries reached. Restarting from the beginning."); + continue 'outer; + } - let signature = response_json["signature"].as_str().ok_or_else(|| { - ClientError::from(ClientErrorKind::Custom( - "Signature not found in response".to_string(), - )) - })?; - - let signature = Signature::from_str(signature).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Signature parsing error: {}", - e - ))) - })?; - - // Skip confirmation if requested - if skip_confirm { - progress_bar.finish_with_message(format!("Sent: {}", signature)); - return Ok(signature); - } + progress_bar.set_message(format!("Submitting transaction... (attempt {})", attempts)); + + // Prepare transaction + let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; + let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); + if signer.pubkey() == fee_payer.pubkey() { + tx.sign(&[&signer], recent_blockhash); + } else { + tx.sign(&[&signer, &fee_payer], recent_blockhash); + } + + let tx_data = + base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Bincode serialization error: {}", + e + ))) + })?); - // Confirm transaction - progress_bar.set_message("Confirming transaction..."); - for _ in 0..CONFIRM_RETRIES { - std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); - match self.rpc_client.get_signature_status(&signature).await { - Ok(Some(status)) => { - if status.is_ok() { - let now = Local::now(); - let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); - progress_bar.println(format!(" Timestamp: {}", formatted_time)); - progress_bar.finish_with_message(format!( - "{} {}", - "OK".bold().green(), - signature - )); - return Ok(signature); + // Prepare request + let request = PostSubmitRequest { + transaction: TransactionMessage { + content: tx_data, + is_cleanup: false, + }, + skip_pre_flight: true, + front_running_protection: Some(true), + tip: self.priority_fee, + use_staked_rpcs: Some(true), + fast_best_effort: Some(false), + }; + + // Submit transaction + progress_bar.set_message("Submitting transaction to Bloxroute..."); + let client = reqwest::Client::new(); + let response = client + .post(BLOXROUTE_URL_LOCAL) + .json(&request) + .send() + .await + .map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!("Request error: {}", e))) + })?; + + let status = response.status(); + let response_text = response.text().await.map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Error reading response body: {}", + e + ))) + })?; + + progress_bar.println(format!("Response status: {}", status)); + progress_bar.println(format!("Raw response: {}", response_text)); + + if status.is_success() { + let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Error parsing JSON response: {}", + e + ))) + })?; + + let signature_str = json_response["signature"].as_str().ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "Signature not found in response".to_string(), + )) + })?; + + signature = Some(Signature::from_str(signature_str).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Signature parsing error: {}", + e + ))) + })?); + + if skip_confirm { + progress_bar.finish_with_message(format!("Sent: {}", signature.unwrap())); + return Ok(signature.unwrap()); + } + + break 'submission; + } else { + let json_response: Value = serde_json::from_str(&response_text).unwrap_or_default(); + if let Some(code) = json_response["code"].as_i64() { + match code { + 6 => { + progress_bar + .println("Transaction already submitted. Moving to confirmation."); + if let Some(sig) = json_response["signature"].as_str() { + signature = Some(Signature::from_str(sig).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Signature parsing error: {}", + e + ))) + })?); + break 'submission; + } else { + progress_bar.println("No signature found in 'already submitted' response. Retrying..."); + } + } + _ => { + progress_bar.println(format!( + "Bloxroute submission failed (code {}). Retrying with new blockhash...", + code + )); + } + } } else { - return Err(ClientError::from(ClientErrorKind::Custom(format!( - "Transaction failed: {:?}", - status - )))); + progress_bar + .println("Bloxroute submission failed. Retrying with new blockhash..."); } } - Ok(None) => continue, - Err(err) => { - progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); + + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + } + + // Confirmation stage + let sig = signature.ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "No signature available for confirmation".into(), + )) + })?; + + progress_bar.set_message("Confirming transaction..."); + for attempt in 1..=CONFIRM_RETRIES { + std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); + progress_bar.println(format!("Confirmation attempt {} of {}", attempt, CONFIRM_RETRIES)); + + match self + .rpc_client + .get_signature_status_with_commitment(&sig, CommitmentConfig::confirmed()) + .await + { + Ok(Some(status)) => { + progress_bar.println(format!(" Received status: {:?}", status)); + match status { + Ok(()) => { + let now = Local::now(); + let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); + progress_bar.println(format!(" Timestamp: {}", formatted_time)); + progress_bar.finish_with_message(format!( + "{} {}", + "OK".bold().green(), + sig + )); + return Ok(sig); + } + Err(err) => match err { + TransactionError::InstructionError( + _, + InstructionError::Custom(err_code), + ) => { + if err_code == 0x1 { + progress_bar.println("Invalid hash. Restarting from the beginning..."); + continue 'outer; + } else if err_code == OreError::NeedsReset as u32 { + progress_bar.println("Needs reset. Restarting from the beginning..."); + continue 'outer; + } else { + progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); + } + } + _ => { + progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); + continue 'outer; + } + }, + } + } + Ok(None) => { + if attempt == CONFIRM_RETRIES { + progress_bar.println("Transaction not found after all retries. Restarting from the beginning..."); + continue 'outer; + } else { + progress_bar.println(" Transaction not yet processed. Continuing to next attempt."); + } + } + Err(err) => { + progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); + if attempt == CONFIRM_RETRIES { + progress_bar.println("Failed to get signature status after all retries. Restarting from the beginning..."); + continue 'outer; + } else { + progress_bar.println(" Failed to get signature status. Continuing to next attempt."); + } + } } } } - - Err(ClientError::from(ClientErrorKind::Custom( - "Transaction confirmation timeout".into(), - ))) } } From 03975b113070824b2cb3ec298cb7a27fff7c7a28 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Mon, 19 Aug 2024 16:30:03 -0600 Subject: [PATCH 04/28] priority fee -> tip --- src/mine.rs | 14 +++++-- src/send_and_confirm_bx.rs | 81 +++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index e673d829..417bec95 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -104,10 +104,18 @@ impl Miner { if args.bloxroute { // submit transaction to bloxroute println!("Submitting transaction to bloxroute"); - match self.send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false).await { - Ok(signature) => println!("Transaction submitted successfully. Signature: {}", signature), + match self + .send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false) + .await + { + Ok(signature) => println!( + "Transaction submitted successfully. Signature: {}", + signature + ), Err(e) => { - if e.to_string().contains("Invalid hash") || e.to_string().contains("Needs reset") { + if e.to_string().contains("Invalid hash") + || e.to_string().contains("Needs reset") + { println!("Refreshing miner state due to: {}", e); continue; } else { diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 14c5075b..dde1e9fa 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -74,18 +74,18 @@ impl Miner { self.priority_fee.unwrap_or(0), )); - if let Some(priority_fee) = self.priority_fee { - if priority_fee > 0 { - let tip_amount = priority_fee / 2; - let tip_pubkey = - Pubkey::from_str("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY").unwrap(); - let tip_instruction = - system_instruction::transfer(&signer.pubkey(), &tip_pubkey, tip_amount); - final_ixs.push(tip_instruction); - progress_bar.println(format!(" Additional tip: {} lamports", tip_amount)); - } else { - progress_bar.println(" No additional tip: Priority fee is zero"); - } + let tip = *self.tip.read().unwrap(); + + if tip > 0 { + let tip_amount = tip / 2; + let tip_pubkey = + Pubkey::from_str("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY").unwrap(); + let tip_instruction = + system_instruction::transfer(&signer.pubkey(), &tip_pubkey, tip_amount); + final_ixs.push(tip_instruction); + progress_bar.println(format!(" Additional tip: {} lamports", tip_amount)); + } else { + progress_bar.println(" No additional tip: Priority fee is zero"); } final_ixs.extend_from_slice(ixs); @@ -107,11 +107,13 @@ impl Miner { 'submission: loop { attempts += 1; if attempts > GATEWAY_RETRIES { - progress_bar.println("Max gateway retries reached. Restarting from the beginning."); + progress_bar + .println("Max gateway retries reached. Restarting from the beginning."); continue 'outer; } - progress_bar.set_message(format!("Submitting transaction... (attempt {})", attempts)); + progress_bar + .set_message(format!("Submitting transaction... (attempt {})", attempts)); // Prepare transaction let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; @@ -122,13 +124,14 @@ impl Miner { tx.sign(&[&signer, &fee_payer], recent_blockhash); } - let tx_data = - base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { + let tx_data = base64::prelude::BASE64_STANDARD.encode( + bincode::serialize(&tx).map_err(|e| { ClientError::from(ClientErrorKind::Custom(format!( "Bincode serialization error: {}", e ))) - })?); + })?, + ); // Prepare request let request = PostSubmitRequest { @@ -167,12 +170,13 @@ impl Miner { progress_bar.println(format!("Raw response: {}", response_text)); if status.is_success() { - let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Error parsing JSON response: {}", - e - ))) - })?; + let json_response: Value = + serde_json::from_str(&response_text).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Error parsing JSON response: {}", + e + ))) + })?; let signature_str = json_response["signature"].as_str().ok_or_else(|| { ClientError::from(ClientErrorKind::Custom( @@ -194,12 +198,14 @@ impl Miner { break 'submission; } else { - let json_response: Value = serde_json::from_str(&response_text).unwrap_or_default(); + let json_response: Value = + serde_json::from_str(&response_text).unwrap_or_default(); if let Some(code) = json_response["code"].as_i64() { match code { 6 => { - progress_bar - .println("Transaction already submitted. Moving to confirmation."); + progress_bar.println( + "Transaction already submitted. Moving to confirmation.", + ); if let Some(sig) = json_response["signature"].as_str() { signature = Some(Signature::from_str(sig).map_err(|e| { ClientError::from(ClientErrorKind::Custom(format!( @@ -238,8 +244,11 @@ impl Miner { progress_bar.set_message("Confirming transaction..."); for attempt in 1..=CONFIRM_RETRIES { std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); - progress_bar.println(format!("Confirmation attempt {} of {}", attempt, CONFIRM_RETRIES)); - + progress_bar.println(format!( + "Confirmation attempt {} of {}", + attempt, CONFIRM_RETRIES + )); + match self .rpc_client .get_signature_status_with_commitment(&sig, CommitmentConfig::confirmed()) @@ -265,10 +274,14 @@ impl Miner { InstructionError::Custom(err_code), ) => { if err_code == 0x1 { - progress_bar.println("Invalid hash. Restarting from the beginning..."); + progress_bar.println( + "Invalid hash. Restarting from the beginning...", + ); continue 'outer; } else if err_code == OreError::NeedsReset as u32 { - progress_bar.println("Needs reset. Restarting from the beginning..."); + progress_bar.println( + "Needs reset. Restarting from the beginning...", + ); continue 'outer; } else { progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); @@ -286,7 +299,9 @@ impl Miner { progress_bar.println("Transaction not found after all retries. Restarting from the beginning..."); continue 'outer; } else { - progress_bar.println(" Transaction not yet processed. Continuing to next attempt."); + progress_bar.println( + " Transaction not yet processed. Continuing to next attempt.", + ); } } Err(err) => { @@ -295,7 +310,9 @@ impl Miner { progress_bar.println("Failed to get signature status after all retries. Restarting from the beginning..."); continue 'outer; } else { - progress_bar.println(" Failed to get signature status. Continuing to next attempt."); + progress_bar.println( + " Failed to get signature status. Continuing to next attempt.", + ); } } } From 03c51b54d3afe0232b8421f44765244934f07916 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Mon, 19 Aug 2024 16:30:37 -0600 Subject: [PATCH 05/28] switch url remote --- src/send_and_confirm_bx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index dde1e9fa..1e9e1cd9 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -28,7 +28,7 @@ const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 750; const CONFIRM_RETRIES: usize = 12; const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; -const BLOXROUTE_URL_LOCAL: &str = "http://localhost:9000/api/v2/mine-ore"; +// const BLOXROUTE_URL_LOCAL: &str = "http://localhost:9000/api/v2/mine-ore"; #[derive(Serialize)] struct TransactionMessage { @@ -150,7 +150,7 @@ impl Miner { progress_bar.set_message("Submitting transaction to Bloxroute..."); let client = reqwest::Client::new(); let response = client - .post(BLOXROUTE_URL_LOCAL) + .post(BLOXROUTE_URL) .json(&request) .send() .await From 1ccd987785233d45e30f313fbf19a4ed59359142 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 07:59:16 -0600 Subject: [PATCH 06/28] adjust re-submit logic --- src/send_and_confirm_bx.rs | 188 +++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 100 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 1e9e1cd9..679887d9 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -90,32 +90,22 @@ impl Miner { final_ixs.extend_from_slice(ixs); - let mut outer_attempts = 0; - const MAX_OUTER_ATTEMPTS: usize = 3; + let mut attempts = 0; + let signature: Option; - 'outer: loop { - outer_attempts += 1; - if outer_attempts > MAX_OUTER_ATTEMPTS { + loop { + attempts += 1; + if attempts > GATEWAY_RETRIES { return Err(ClientError::from(ClientErrorKind::Custom( - "Max outer retries reached".into(), + "Max gateway retries reached".into(), ))); } - let mut attempts = 0; - let signature: Option; + progress_bar + .set_message(format!("Submitting transaction... (attempt {})", attempts)); - 'submission: loop { - attempts += 1; - if attempts > GATEWAY_RETRIES { - progress_bar - .println("Max gateway retries reached. Restarting from the beginning."); - continue 'outer; - } - - progress_bar - .set_message(format!("Submitting transaction... (attempt {})", attempts)); - - // Prepare transaction + // Prepare transaction + if attempts % 10 == 1 { let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); if signer.pubkey() == fee_payer.pubkey() { @@ -196,7 +186,7 @@ impl Miner { return Ok(signature.unwrap()); } - break 'submission; + break; } else { let json_response: Value = serde_json::from_str(&response_text).unwrap_or_default(); @@ -213,7 +203,7 @@ impl Miner { e ))) })?); - break 'submission; + break; } else { progress_bar.println("No signature found in 'already submitted' response. Retrying..."); } @@ -230,93 +220,91 @@ impl Miner { .println("Bloxroute submission failed. Retrying with new blockhash..."); } } - - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); } - // Confirmation stage - let sig = signature.ok_or_else(|| { - ClientError::from(ClientErrorKind::Custom( - "No signature available for confirmation".into(), - )) - })?; + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + } - progress_bar.set_message("Confirming transaction..."); - for attempt in 1..=CONFIRM_RETRIES { - std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); - progress_bar.println(format!( - "Confirmation attempt {} of {}", - attempt, CONFIRM_RETRIES - )); + // Confirmation stage + let sig = signature.ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "No signature available for confirmation".into(), + )) + })?; - match self - .rpc_client - .get_signature_status_with_commitment(&sig, CommitmentConfig::confirmed()) - .await - { - Ok(Some(status)) => { - progress_bar.println(format!(" Received status: {:?}", status)); - match status { - Ok(()) => { - let now = Local::now(); - let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); - progress_bar.println(format!(" Timestamp: {}", formatted_time)); - progress_bar.finish_with_message(format!( - "{} {}", - "OK".bold().green(), - sig - )); - return Ok(sig); - } - Err(err) => match err { - TransactionError::InstructionError( - _, - InstructionError::Custom(err_code), - ) => { - if err_code == 0x1 { - progress_bar.println( - "Invalid hash. Restarting from the beginning...", - ); - continue 'outer; - } else if err_code == OreError::NeedsReset as u32 { - progress_bar.println( - "Needs reset. Restarting from the beginning...", - ); - continue 'outer; - } else { - progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); - } - } - _ => { - progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); - continue 'outer; - } - }, + progress_bar.set_message("Confirming transaction..."); + for attempt in 1..=CONFIRM_RETRIES { + std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); + progress_bar.println(format!( + "Confirmation attempt {} of {}", + attempt, CONFIRM_RETRIES + )); + + match self + .rpc_client + .get_signature_status_with_commitment(&sig, CommitmentConfig::confirmed()) + .await + { + Ok(Some(status)) => { + progress_bar.println(format!(" Received status: {:?}", status)); + match status { + Ok(()) => { + let now = Local::now(); + let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); + progress_bar.println(format!(" Timestamp: {}", formatted_time)); + progress_bar.finish_with_message(format!( + "{} {}", + "OK".bold().green(), + sig + )); + return Ok(sig); } + Err(err) => match err { + TransactionError::InstructionError( + _, + InstructionError::Custom(err_code), + ) => { + if err_code == OreError::NeedsReset as u32 { + progress_bar.println("Needs reset. Restarting from the beginning..."); + return Err(ClientError::from(ClientErrorKind::Custom("Needs reset".into()))); + } else { + progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); + } + } + _ => { + progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); + return Err(ClientError::from(ClientErrorKind::Custom(format!("Transaction failed: {:?}", err)))); + } + }, } - Ok(None) => { - if attempt == CONFIRM_RETRIES { - progress_bar.println("Transaction not found after all retries. Restarting from the beginning..."); - continue 'outer; - } else { - progress_bar.println( - " Transaction not yet processed. Continuing to next attempt.", - ); - } + } + Ok(None) => { + if attempt == CONFIRM_RETRIES { + return Err(ClientError::from(ClientErrorKind::Custom( + "Transaction not found after all retries".into(), + ))); + } else { + progress_bar.println( + " Transaction not yet processed. Continuing to next attempt.", + ); } - Err(err) => { - progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); - if attempt == CONFIRM_RETRIES { - progress_bar.println("Failed to get signature status after all retries. Restarting from the beginning..."); - continue 'outer; - } else { - progress_bar.println( - " Failed to get signature status. Continuing to next attempt.", - ); - } + } + Err(err) => { + progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); + if attempt == CONFIRM_RETRIES { + return Err(ClientError::from(ClientErrorKind::Custom( + "Failed to get signature status after all retries".into(), + ))); + } else { + progress_bar.println( + " Failed to get signature status. Continuing to next attempt.", + ); } } } } + Err(ClientError::from(ClientErrorKind::Custom( + "Transaction confirmation failed after all retries".into(), + ))) } -} +} \ No newline at end of file From f1c662028b25a9f3c2ed03db6b0e94141b920b29 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 08:09:31 -0600 Subject: [PATCH 07/28] err 6 refactor --- src/send_and_confirm_bx.rs | 53 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 679887d9..5bfcfa7a 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -101,8 +101,7 @@ impl Miner { ))); } - progress_bar - .set_message(format!("Submitting transaction... (attempt {})", attempts)); + progress_bar.set_message(format!("Submitting transaction... (attempt {})", attempts)); // Prepare transaction if attempts % 10 == 1 { @@ -196,16 +195,10 @@ impl Miner { progress_bar.println( "Transaction already submitted. Moving to confirmation.", ); - if let Some(sig) = json_response["signature"].as_str() { - signature = Some(Signature::from_str(sig).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Signature parsing error: {}", - e - ))) - })?); + if let Some(sig) = signature { break; } else { - progress_bar.println("No signature found in 'already submitted' response. Retrying..."); + progress_bar.println("No signature available for already submitted transaction. Retrying..."); } } _ => { @@ -259,23 +252,31 @@ impl Miner { )); return Ok(sig); } - Err(err) => match err { - TransactionError::InstructionError( - _, - InstructionError::Custom(err_code), - ) => { - if err_code == OreError::NeedsReset as u32 { - progress_bar.println("Needs reset. Restarting from the beginning..."); - return Err(ClientError::from(ClientErrorKind::Custom("Needs reset".into()))); - } else { - progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); + Err(err) => { + match err { + TransactionError::InstructionError( + _, + InstructionError::Custom(err_code), + ) => { + if err_code == OreError::NeedsReset as u32 { + progress_bar.println( + "Needs reset. Restarting from the beginning...", + ); + return Err(ClientError::from(ClientErrorKind::Custom( + "Needs reset".into(), + ))); + } else { + progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); + } + } + _ => { + progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); + return Err(ClientError::from(ClientErrorKind::Custom( + format!("Transaction failed: {:?}", err), + ))); } } - _ => { - progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); - return Err(ClientError::from(ClientErrorKind::Custom(format!("Transaction failed: {:?}", err)))); - } - }, + } } } Ok(None) => { @@ -307,4 +308,4 @@ impl Miner { "Transaction confirmation failed after all retries".into(), ))) } -} \ No newline at end of file +} From 9f093331d935d1c9e541183c86ea7625e6ebc63f Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 08:18:53 -0600 Subject: [PATCH 08/28] fix build --- src/send_and_confirm_bx.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 5bfcfa7a..3d30fb80 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -91,7 +91,7 @@ impl Miner { final_ixs.extend_from_slice(ixs); let mut attempts = 0; - let signature: Option; + let mut signature: Option = None; loop { attempts += 1; @@ -195,11 +195,7 @@ impl Miner { progress_bar.println( "Transaction already submitted. Moving to confirmation.", ); - if let Some(sig) = signature { - break; - } else { - progress_bar.println("No signature available for already submitted transaction. Retrying..."); - } + break; } _ => { progress_bar.println(format!( From af4d40edb53dc1281f8710845dcb3e1ef25aae38 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 10:43:39 -0600 Subject: [PATCH 09/28] add more logging --- src/mine.rs | 12 +----------- src/utils.rs | 5 +++++ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 417bec95..8c946960 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -112,17 +112,7 @@ impl Miner { "Transaction submitted successfully. Signature: {}", signature ), - Err(e) => { - if e.to_string().contains("Invalid hash") - || e.to_string().contains("Needs reset") - { - println!("Refreshing miner state due to: {}", e); - continue; - } else { - println!("Error submitting transaction: {:?}", e); - // Handle other errors as needed - } - } + Err(e) => println!("Error submitting transaction: {:?}", e), } } else { // Submit transaction diff --git a/src/utils.rs b/src/utils.rs index 9326cc19..75dbd235 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -45,11 +45,16 @@ pub async fn get_updated_proof_with_authority( authority: Pubkey, lash_hash_at: i64, ) -> Proof { + println!( + "Entering get_updated_proof_with_authority. Authority: {}, Last hash at: {}", + authority, lash_hash_at + ); loop { let proof = get_proof_with_authority(client, authority).await; if proof.last_hash_at.gt(&lash_hash_at) { return proof; } + println!("No proof found yet. Sleeping..."); std::thread::sleep(Duration::from_millis(1000)); } } From ec74f1ad7781ee9e6d7280f64650ed0d262836ec Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 18:12:45 -0600 Subject: [PATCH 10/28] retry on endpoint fail --- src/send_and_confirm_bx.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 3d30fb80..3df3fd5d 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -27,8 +27,8 @@ const GATEWAY_RETRIES: usize = 150; const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 750; const CONFIRM_RETRIES: usize = 12; -const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; -// const BLOXROUTE_URL_LOCAL: &str = "http://localhost:9000/api/v2/mine-ore"; +// const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; +const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; #[derive(Serialize)] struct TransactionMessage { @@ -138,14 +138,15 @@ impl Miner { // Submit transaction progress_bar.set_message("Submitting transaction to Bloxroute..."); let client = reqwest::Client::new(); - let response = client - .post(BLOXROUTE_URL) - .json(&request) - .send() - .await - .map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!("Request error: {}", e))) - })?; + let response = match client.post(BLOXROUTE_URL).json(&request).send().await { + Ok(response) => response, + Err(e) => { + progress_bar + .println(format!("Bloxroute request error: {}. Retrying...", e)); + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + continue; + } + }; let status = response.status(); let response_text = response.text().await.map_err(|e| { From a74899b2c7952f4ec9f11b105fec3d39d7aace83 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 20 Aug 2024 18:16:16 -0600 Subject: [PATCH 11/28] switch endpoint --- src/send_and_confirm_bx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 3df3fd5d..fa6641ac 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -27,8 +27,8 @@ const GATEWAY_RETRIES: usize = 150; const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 750; const CONFIRM_RETRIES: usize = 12; -// const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; -const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; +const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; +// const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; #[derive(Serialize)] struct TransactionMessage { From a3c43014e74a858255446addee33b104130fd480 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Wed, 21 Aug 2024 13:59:11 -0600 Subject: [PATCH 12/28] add rpc fallback & refactor --- src/mine.rs | 2 +- src/send_and_confirm.rs | 4 +- src/send_and_confirm_bx.rs | 390 +++++++++++++++++++------------------ 3 files changed, 203 insertions(+), 193 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 8c946960..a985a3dd 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -105,7 +105,7 @@ impl Miner { // submit transaction to bloxroute println!("Submitting transaction to bloxroute"); match self - .send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget), false) + .send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget)) .await { Ok(signature) => println!( diff --git a/src/send_and_confirm.rs b/src/send_and_confirm.rs index 2c81ac33..02f2519b 100644 --- a/src/send_and_confirm.rs +++ b/src/send_and_confirm.rs @@ -351,7 +351,7 @@ impl Miner { } } -fn log_error(progress_bar: &ProgressBar, err: &str, finish: bool) { +pub fn log_error(progress_bar: &ProgressBar, err: &str, finish: bool) { if finish { progress_bar.finish_with_message(format!("{} {}", "ERROR".bold().red(), err)); } else { @@ -359,6 +359,6 @@ fn log_error(progress_bar: &ProgressBar, err: &str, finish: bool) { } } -fn log_warning(progress_bar: &ProgressBar, msg: &str) { +pub fn log_warning(progress_bar: &ProgressBar, msg: &str) { progress_bar.println(format!(" {} {}", "WARNING".bold().yellow(), msg)); } diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index fa6641ac..d1f5dd14 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -4,29 +4,30 @@ use colored::Colorize; use ore_api::error::OreError; use serde::Serialize; use serde_json::Value; -use solana_client::client_error::{ClientError, ClientErrorKind, Result as ClientResult}; -use solana_program::{ - instruction::{Instruction, InstructionError}, - pubkey::Pubkey, - system_instruction, +use solana_client::{ + client_error::{ClientError, ClientErrorKind, Result as ClientResult}, + rpc_config::RpcSendTransactionConfig, }; +use solana_program::{instruction::Instruction, pubkey::Pubkey, system_instruction}; use solana_rpc_client::spinner; use solana_sdk::{ - commitment_config::CommitmentConfig, - compute_budget::ComputeBudgetInstruction, - signature::Signature, - signer::Signer, - transaction::{Transaction, TransactionError}, + commitment_config::CommitmentLevel, compute_budget::ComputeBudgetInstruction, + signature::Signature, signer::Signer, transaction::Transaction, }; +use solana_transaction_status::{TransactionConfirmationStatus, UiTransactionEncoding}; use std::str::FromStr; use std::time::Duration; -use crate::{send_and_confirm::ComputeBudget, Miner}; +use crate::{ + send_and_confirm::{log_error, log_warning, ComputeBudget}, + utils::get_latest_blockhash_with_retries, + Miner, +}; const GATEWAY_RETRIES: usize = 150; const GATEWAY_DELAY: u64 = 0; -const CONFIRM_DELAY: u64 = 750; -const CONFIRM_RETRIES: usize = 12; +const CONFIRM_DELAY: u64 = 500; +const CONFIRM_RETRIES: usize = 16; const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; // const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; @@ -56,7 +57,6 @@ impl Miner { &self, ixs: &[Instruction], compute_budget: ComputeBudget, - skip_confirm: bool, ) -> ClientResult { let progress_bar = spinner::new_progress_bar(); let signer = self.signer(); @@ -75,14 +75,15 @@ impl Miner { )); let tip = *self.tip.read().unwrap(); - if tip > 0 { let tip_amount = tip / 2; let tip_pubkey = Pubkey::from_str("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY").unwrap(); - let tip_instruction = - system_instruction::transfer(&signer.pubkey(), &tip_pubkey, tip_amount); - final_ixs.push(tip_instruction); + final_ixs.push(system_instruction::transfer( + &signer.pubkey(), + &tip_pubkey, + tip_amount, + )); progress_bar.println(format!(" Additional tip: {} lamports", tip_amount)); } else { progress_bar.println(" No additional tip: Priority fee is zero"); @@ -92,7 +93,6 @@ impl Miner { let mut attempts = 0; let mut signature: Option = None; - loop { attempts += 1; if attempts > GATEWAY_RETRIES { @@ -103,206 +103,216 @@ impl Miner { progress_bar.set_message(format!("Submitting transaction... (attempt {})", attempts)); - // Prepare transaction - if attempts % 10 == 1 { - let recent_blockhash = self.rpc_client.get_latest_blockhash().await?; - let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); - if signer.pubkey() == fee_payer.pubkey() { - tx.sign(&[&signer], recent_blockhash); - } else { - tx.sign(&[&signer, &fee_payer], recent_blockhash); - } + let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); - let tx_data = base64::prelude::BASE64_STANDARD.encode( - bincode::serialize(&tx).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Bincode serialization error: {}", - e - ))) - })?, - ); + if attempts % 10 == 0 { + // Reset the compute unit price + if self.dynamic_fee { + let fee = match self.dynamic_fee().await { + Ok(fee) => { + progress_bar.println(format!(" Priority fee: {} microlamports", fee)); + fee + } + Err(err) => { + let fee = self.priority_fee.unwrap_or(0); + log_warning( + &progress_bar, + &format!( + "{} Falling back to static value: {} microlamports", + err, fee + ), + ); + fee + } + }; - // Prepare request - let request = PostSubmitRequest { - transaction: TransactionMessage { - content: tx_data, - is_cleanup: false, - }, - skip_pre_flight: true, - front_running_protection: Some(true), - tip: self.priority_fee, - use_staked_rpcs: Some(true), - fast_best_effort: Some(false), - }; + final_ixs.remove(1); + final_ixs.insert(1, ComputeBudgetInstruction::set_compute_unit_price(fee)); + tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); + } - // Submit transaction - progress_bar.set_message("Submitting transaction to Bloxroute..."); - let client = reqwest::Client::new(); - let response = match client.post(BLOXROUTE_URL).json(&request).send().await { - Ok(response) => response, - Err(e) => { - progress_bar - .println(format!("Bloxroute request error: {}. Retrying...", e)); - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); - continue; - } - }; + // Resign the tx + let (hash, _slot) = get_latest_blockhash_with_retries(&self.rpc_client).await?; + if signer.pubkey() == fee_payer.pubkey() { + tx.sign(&[&signer], hash); + } else { + tx.sign(&[&signer, &fee_payer], hash); + } + } - let status = response.status(); - let response_text = response.text().await.map_err(|e| { + let tx_data = + base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { ClientError::from(ClientErrorKind::Custom(format!( - "Error reading response body: {}", + "Serialization error: {}", e ))) - })?; - - progress_bar.println(format!("Response status: {}", status)); - progress_bar.println(format!("Raw response: {}", response_text)); + })?); - if status.is_success() { - let json_response: Value = - serde_json::from_str(&response_text).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Error parsing JSON response: {}", - e - ))) - })?; + // Prepare request + let request = PostSubmitRequest { + transaction: TransactionMessage { + content: tx_data, + is_cleanup: false, + }, + skip_pre_flight: true, + front_running_protection: Some(true), + tip: self.priority_fee, + use_staked_rpcs: Some(true), + fast_best_effort: Some(false), + }; - let signature_str = json_response["signature"].as_str().ok_or_else(|| { - ClientError::from(ClientErrorKind::Custom( - "Signature not found in response".to_string(), - )) - })?; + // Submit transaction + progress_bar.set_message("Submitting transaction to Bloxroute..."); + let client = reqwest::Client::new(); + let response = match client.post(BLOXROUTE_URL).json(&request).send().await { + Ok(response) => response, + Err(e) => { + progress_bar.println(format!("Bloxroute request error: {}. Retrying...", e)); + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + continue; + } + }; - signature = Some(Signature::from_str(signature_str).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Signature parsing error: {}", - e - ))) - })?); + let status = response.status(); + let response_text = response.text().await.map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Failed to get response text: {}", + e + ))) + })?; - if skip_confirm { - progress_bar.finish_with_message(format!("Sent: {}", signature.unwrap())); - return Ok(signature.unwrap()); - } + let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "JSON parsing error: {}", + e + ))) + })?; - break; - } else { - let json_response: Value = - serde_json::from_str(&response_text).unwrap_or_default(); - if let Some(code) = json_response["code"].as_i64() { - match code { - 6 => { - progress_bar.println( - "Transaction already submitted. Moving to confirmation.", - ); - break; - } - _ => { + if status.is_success() { + let signature_str = json_response["signature"].as_str().ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "Signature not found in response".to_string(), + )) + })?; + signature = Some(Signature::from_str(signature_str).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!("Invalid signature: {}", e))) + })?); + } else { + match &json_response["code"] { + Value::Number(n) => { + if let Some(code) = n.as_u64() { + if code != 6 { progress_bar.println(format!( - "Bloxroute submission failed (code {}). Retrying with new blockhash...", - code + "Bloxroute Endpoint Response: {}", + json_response )); + progress_bar.println("Sending via fallback RPC..."); + // attempt to send via RPC client + let send_cfg = RpcSendTransactionConfig { + skip_preflight: true, + preflight_commitment: Some(CommitmentLevel::Confirmed), + encoding: Some(UiTransactionEncoding::Base64), + max_retries: Some(0), + min_context_slot: None, + }; + + self.rpc_client + .send_transaction_with_config(&tx, send_cfg) + .await + .ok(); } } - } else { - progress_bar - .println("Bloxroute submission failed. Retrying with new blockhash..."); } + _ => {} } } - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); - } - - // Confirmation stage - let sig = signature.ok_or_else(|| { - ClientError::from(ClientErrorKind::Custom( - "No signature available for confirmation".into(), - )) - })?; + if let Some(sig) = signature { + 'confirm: for _ in 0..CONFIRM_RETRIES { + std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); + match self.rpc_client.get_signature_statuses(&[sig]).await { + Ok(signature_statuses) => { + for status in signature_statuses.value { + if let Some(status) = status { + if let Some(err) = status.err { + match err { + // Instruction error + solana_sdk::transaction::TransactionError::InstructionError(_, err) => { + match err { + // Custom instruction error, parse into OreError + solana_program::instruction::InstructionError::Custom(err_code) => { + match err_code { + e if e == OreError::NeedsReset as u32 => { + attempts = 0; + log_error(&progress_bar, "Needs reset. Retrying...", false); + break 'confirm; + }, + _ => { + log_error(&progress_bar, &err.to_string(), true); + return Err(ClientError { + request: None, + kind: ClientErrorKind::Custom(err.to_string()), + }); + } + } + }, - progress_bar.set_message("Confirming transaction..."); - for attempt in 1..=CONFIRM_RETRIES { - std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); - progress_bar.println(format!( - "Confirmation attempt {} of {}", - attempt, CONFIRM_RETRIES - )); + // Non custom instruction error, return + _ => { + log_error(&progress_bar, &err.to_string(), true); + return Err(ClientError { + request: None, + kind: ClientErrorKind::Custom(err.to_string()), + }); + } + } + }, - match self - .rpc_client - .get_signature_status_with_commitment(&sig, CommitmentConfig::confirmed()) - .await - { - Ok(Some(status)) => { - progress_bar.println(format!(" Received status: {:?}", status)); - match status { - Ok(()) => { - let now = Local::now(); - let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string(); - progress_bar.println(format!(" Timestamp: {}", formatted_time)); - progress_bar.finish_with_message(format!( - "{} {}", - "OK".bold().green(), - sig - )); - return Ok(sig); - } - Err(err) => { - match err { - TransactionError::InstructionError( - _, - InstructionError::Custom(err_code), - ) => { - if err_code == OreError::NeedsReset as u32 { - progress_bar.println( - "Needs reset. Restarting from the beginning...", - ); - return Err(ClientError::from(ClientErrorKind::Custom( - "Needs reset".into(), - ))); - } else { - progress_bar.println(format!("Transaction failed with instruction error. Error code: {}. Retrying...", err_code)); + // Non instruction error, return + _ => { + log_error(&progress_bar, &err.to_string(), true); + return Err(ClientError { + request: None, + kind: ClientErrorKind::Custom(err.to_string()), + }); + } + } + } else if let Some(confirmation) = status.confirmation_status { + match confirmation { + TransactionConfirmationStatus::Processed => {} + TransactionConfirmationStatus::Confirmed + | TransactionConfirmationStatus::Finalized => { + let now = Local::now(); + let formatted_time = + now.format("%Y-%m-%d %H:%M:%S").to_string(); + progress_bar.println(format!( + " Timestamp: {}", + formatted_time + )); + progress_bar.finish_with_message(format!( + "{} {}", + "OK".bold().green(), + sig + )); + return Ok(sig); + } + } } } - _ => { - progress_bar.println(format!("Transaction failed: {:?}. Restarting from the beginning...", err)); - return Err(ClientError::from(ClientErrorKind::Custom( - format!("Transaction failed: {:?}", err), - ))); - } } } - } - } - Ok(None) => { - if attempt == CONFIRM_RETRIES { - return Err(ClientError::from(ClientErrorKind::Custom( - "Transaction not found after all retries".into(), - ))); - } else { - progress_bar.println( - " Transaction not yet processed. Continuing to next attempt.", - ); - } - } - Err(err) => { - progress_bar.println(format!(" {} {}", "ERROR".bold().red(), err)); - if attempt == CONFIRM_RETRIES { - return Err(ClientError::from(ClientErrorKind::Custom( - "Failed to get signature status after all retries".into(), - ))); - } else { - progress_bar.println( - " Failed to get signature status. Continuing to next attempt.", - ); + + // Handle confirmation errors + Err(err) => { + log_error(&progress_bar, &err.kind().to_string(), false); + } } } } + + // If we've exhausted all confirmation retries, continue to the next submission attempt + progress_bar.println("Confirmation attempts exhausted. Retrying submission..."); + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); } - Err(ClientError::from(ClientErrorKind::Custom( - "Transaction confirmation failed after all retries".into(), - ))) } } From ab2696f6643a007e7eff6edeb375cb8fb14d3fb7 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Thu, 22 Aug 2024 08:34:18 -0600 Subject: [PATCH 13/28] rm hanging log --- src/utils.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index 75dbd235..bb4c4256 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -54,7 +54,6 @@ pub async fn get_updated_proof_with_authority( if proof.last_hash_at.gt(&lash_hash_at) { return proof; } - println!("No proof found yet. Sleeping..."); std::thread::sleep(Duration::from_millis(1000)); } } From 121c143891d247499ddeb6d989f1a56e8ce24ca0 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Thu, 22 Aug 2024 10:11:51 -0600 Subject: [PATCH 14/28] add more logging --- src/send_and_confirm_bx.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index d1f5dd14..9ff1ee20 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -188,6 +188,11 @@ impl Miner { ))) })?; + progress_bar.println(format!( + "Bloxroute Endpoint Response: {}", + json_response + )); + if status.is_success() { let signature_str = json_response["signature"].as_str().ok_or_else(|| { ClientError::from(ClientErrorKind::Custom( @@ -202,10 +207,6 @@ impl Miner { Value::Number(n) => { if let Some(code) = n.as_u64() { if code != 6 { - progress_bar.println(format!( - "Bloxroute Endpoint Response: {}", - json_response - )); progress_bar.println("Sending via fallback RPC..."); // attempt to send via RPC client let send_cfg = RpcSendTransactionConfig { From 278e5347e416d1d51de1fbbbb5212e1f337310f8 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Thu, 22 Aug 2024 10:51:14 -0600 Subject: [PATCH 15/28] add more logging --- src/send_and_confirm_bx.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 9ff1ee20..2fc9874c 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -181,6 +181,8 @@ impl Miner { ))) })?; + println!("Bloxroute Endpoint Response: {}", response_text); + let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { ClientError::from(ClientErrorKind::Custom(format!( "JSON parsing error: {}", @@ -188,11 +190,6 @@ impl Miner { ))) })?; - progress_bar.println(format!( - "Bloxroute Endpoint Response: {}", - json_response - )); - if status.is_success() { let signature_str = json_response["signature"].as_str().ok_or_else(|| { ClientError::from(ClientErrorKind::Custom( From d7689b30f5daec2477da73e893d3401af13c8da1 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Thu, 22 Aug 2024 12:38:18 -0600 Subject: [PATCH 16/28] fix attempts logic --- src/send_and_confirm_bx.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 2fc9874c..63835b4a 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -94,15 +94,12 @@ impl Miner { let mut attempts = 0; let mut signature: Option = None; loop { - attempts += 1; if attempts > GATEWAY_RETRIES { return Err(ClientError::from(ClientErrorKind::Custom( "Max gateway retries reached".into(), ))); } - progress_bar.set_message(format!("Submitting transaction... (attempt {})", attempts)); - let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); if attempts % 10 == 0 { @@ -161,6 +158,8 @@ impl Miner { fast_best_effort: Some(false), }; + attempts += 1; + // Submit transaction progress_bar.set_message("Submitting transaction to Bloxroute..."); let client = reqwest::Client::new(); From 0be63434d37a758a6b8cf09bfc77e8389ce6a6c4 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Thu, 22 Aug 2024 14:42:14 -0600 Subject: [PATCH 17/28] mv tx outside of loop --- src/send_and_confirm_bx.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 63835b4a..85170933 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -93,6 +93,7 @@ impl Miner { let mut attempts = 0; let mut signature: Option = None; + let mut tx: Transaction = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); loop { if attempts > GATEWAY_RETRIES { return Err(ClientError::from(ClientErrorKind::Custom( @@ -100,8 +101,6 @@ impl Miner { ))); } - let mut tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); - if attempts % 10 == 0 { // Reset the compute unit price if self.dynamic_fee { From 5d2f31aa040fdcb4db2fe5b306e61a719dbacf75 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 23 Aug 2024 08:49:01 -0600 Subject: [PATCH 18/28] add jito + rpc backup --- src/send_and_confirm_bx.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 85170933..15bf3e7e 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -1,6 +1,7 @@ use base64::Engine; use chrono::Local; use colored::Colorize; +use futures::TryFutureExt; use ore_api::error::OreError; use serde::Serialize; use serde_json::Value; @@ -93,7 +94,8 @@ impl Miner { let mut attempts = 0; let mut signature: Option = None; - let mut tx: Transaction = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); + let mut tx: Transaction = + Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); loop { if attempts > GATEWAY_RETRIES { return Err(ClientError::from(ClientErrorKind::Custom( @@ -212,8 +214,11 @@ impl Miner { min_context_slot: None, }; - self.rpc_client + self.jito_client .send_transaction_with_config(&tx, send_cfg) + .or_else(|_| { + self.rpc_client.send_transaction_with_config(&tx, send_cfg) + }) .await .ok(); } From e4113cd001510751ed7cdc3379601696a7b810f2 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Sat, 24 Aug 2024 19:56:28 -0600 Subject: [PATCH 19/28] refactor endpoint code outer loop --- src/send_and_confirm_bx.rs | 176 ++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 79 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 15bf3e7e..4a6062d7 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -25,7 +25,7 @@ use crate::{ Miner, }; -const GATEWAY_RETRIES: usize = 150; +const GATEWAY_RETRIES: usize = 200; const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 500; const CONFIRM_RETRIES: usize = 16; @@ -96,6 +96,8 @@ impl Miner { let mut signature: Option = None; let mut tx: Transaction = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); + let mut skip_submit = false; + loop { if attempts > GATEWAY_RETRIES { return Err(ClientError::from(ClientErrorKind::Custom( @@ -104,7 +106,7 @@ impl Miner { } if attempts % 10 == 0 { - // Reset the compute unit price + // Reset the compute unit price and resign the transaction if self.dynamic_fee { let fee = match self.dynamic_fee().await { Ok(fee) => { @@ -136,95 +138,110 @@ impl Miner { } else { tx.sign(&[&signer, &fee_payer], hash); } - } - - let tx_data = - base64::prelude::BASE64_STANDARD.encode(bincode::serialize(&tx).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Serialization error: {}", - e - ))) - })?); - // Prepare request - let request = PostSubmitRequest { - transaction: TransactionMessage { - content: tx_data, - is_cleanup: false, - }, - skip_pre_flight: true, - front_running_protection: Some(true), - tip: self.priority_fee, - use_staked_rpcs: Some(true), - fast_best_effort: Some(false), - }; + // Reset skip_submit flag as we have a new transaction + skip_submit = false; + } - attempts += 1; + if !skip_submit { + let tx_data = base64::prelude::BASE64_STANDARD.encode( + bincode::serialize(&tx).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Serialization error: {}", + e + ))) + })?, + ); - // Submit transaction - progress_bar.set_message("Submitting transaction to Bloxroute..."); - let client = reqwest::Client::new(); - let response = match client.post(BLOXROUTE_URL).json(&request).send().await { - Ok(response) => response, - Err(e) => { - progress_bar.println(format!("Bloxroute request error: {}. Retrying...", e)); - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); - continue; - } - }; + // Prepare request + let request = PostSubmitRequest { + transaction: TransactionMessage { + content: tx_data, + is_cleanup: false, + }, + skip_pre_flight: true, + front_running_protection: Some(true), + tip: self.priority_fee, + use_staked_rpcs: Some(true), + fast_best_effort: Some(false), + }; - let status = response.status(); - let response_text = response.text().await.map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "Failed to get response text: {}", - e - ))) - })?; + // Submit transaction + progress_bar.set_message("Submitting transaction to Bloxroute..."); + let client = reqwest::Client::new(); + let response = match client.post(BLOXROUTE_URL).json(&request).send().await { + Ok(response) => response, + Err(e) => { + progress_bar + .println(format!("Bloxroute request error: {}. Retrying...", e)); + std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + attempts += 1; + continue; + } + }; - println!("Bloxroute Endpoint Response: {}", response_text); + let status = response.status(); + let response_text = response.text().await.map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Failed to get response text: {}", + e + ))) + })?; - let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!( - "JSON parsing error: {}", - e - ))) - })?; + println!("Bloxroute Endpoint Response: {}", response_text); - if status.is_success() { - let signature_str = json_response["signature"].as_str().ok_or_else(|| { - ClientError::from(ClientErrorKind::Custom( - "Signature not found in response".to_string(), - )) + let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "JSON parsing error: {}", + e + ))) })?; - signature = Some(Signature::from_str(signature_str).map_err(|e| { - ClientError::from(ClientErrorKind::Custom(format!("Invalid signature: {}", e))) - })?); - } else { - match &json_response["code"] { - Value::Number(n) => { - if let Some(code) = n.as_u64() { - if code != 6 { - progress_bar.println("Sending via fallback RPC..."); - // attempt to send via RPC client - let send_cfg = RpcSendTransactionConfig { - skip_preflight: true, - preflight_commitment: Some(CommitmentLevel::Confirmed), - encoding: Some(UiTransactionEncoding::Base64), - max_retries: Some(0), - min_context_slot: None, - }; - self.jito_client - .send_transaction_with_config(&tx, send_cfg) - .or_else(|_| { - self.rpc_client.send_transaction_with_config(&tx, send_cfg) - }) - .await - .ok(); + if status.is_success() { + let signature_str = json_response["signature"].as_str().ok_or_else(|| { + ClientError::from(ClientErrorKind::Custom( + "Signature not found in response".to_string(), + )) + })?; + signature = Some(Signature::from_str(signature_str).map_err(|e| { + ClientError::from(ClientErrorKind::Custom(format!( + "Invalid signature: {}", + e + ))) + })?); + } else { + match &json_response["code"] { + Value::Number(n) => { + if let Some(code) = n.as_u64() { + if code == 6 { + progress_bar.println( + "Transaction already submitted. Skipping submission...", + ); + skip_submit = true; + } else { + progress_bar.println("Sending via fallback RPC..."); + // attempt to send via RPC client + let send_cfg = RpcSendTransactionConfig { + skip_preflight: true, + preflight_commitment: Some(CommitmentLevel::Confirmed), + encoding: Some(UiTransactionEncoding::Base64), + max_retries: Some(0), + min_context_slot: None, + }; + + self.jito_client + .send_transaction_with_config(&tx, send_cfg) + .or_else(|_| { + self.rpc_client + .send_transaction_with_config(&tx, send_cfg) + }) + .await + .ok(); + } } } + _ => {} } - _ => {} } } @@ -314,6 +331,7 @@ impl Miner { // If we've exhausted all confirmation retries, continue to the next submission attempt progress_bar.println("Confirmation attempts exhausted. Retrying submission..."); std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + attempts += 1; } } } From 330168f17886d2ac9c49337ed6b5159a1a78542f Mon Sep 17 00:00:00 2001 From: Lanikean Date: Sun, 25 Aug 2024 12:16:38 -0600 Subject: [PATCH 20/28] more logging --- src/send_and_confirm_bx.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 4a6062d7..45cddc6d 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -25,10 +25,10 @@ use crate::{ Miner, }; -const GATEWAY_RETRIES: usize = 200; +const GATEWAY_RETRIES: usize = 50; const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 500; -const CONFIRM_RETRIES: usize = 16; +const CONFIRM_RETRIES: usize = 8; const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; // const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; @@ -99,13 +99,17 @@ impl Miner { let mut skip_submit = false; loop { + progress_bar.println(format!("Attempt {} of {}", attempts + 1, GATEWAY_RETRIES)); + progress_bar.println(format!("skip_submit is currently {}", skip_submit)); if attempts > GATEWAY_RETRIES { + progress_bar.println("Max gateway retries reached. Exiting send_and_confirm_bx."); return Err(ClientError::from(ClientErrorKind::Custom( "Max gateway retries reached".into(), ))); } if attempts % 10 == 0 { + progress_bar.println("Resigning transaction and resetting skip_submit"); // Reset the compute unit price and resign the transaction if self.dynamic_fee { let fee = match self.dynamic_fee().await { @@ -144,8 +148,11 @@ impl Miner { } if !skip_submit { + progress_bar.println("Preparing to submit to Bloxroute"); + let tx_data = base64::prelude::BASE64_STANDARD.encode( bincode::serialize(&tx).map_err(|e| { + progress_bar.println("Failed to serialize TX"); ClientError::from(ClientErrorKind::Custom(format!( "Serialization error: {}", e @@ -182,15 +189,18 @@ impl Miner { let status = response.status(); let response_text = response.text().await.map_err(|e| { + progress_bar.println(format!("Failed to get response text: {}", e)); ClientError::from(ClientErrorKind::Custom(format!( "Failed to get response text: {}", e ))) })?; + println!("Response Status: {}", status); println!("Bloxroute Endpoint Response: {}", response_text); let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { + progress_bar.println(format!("Failed to get parse reponse json: {}", e)); ClientError::from(ClientErrorKind::Custom(format!( "JSON parsing error: {}", e @@ -199,11 +209,13 @@ impl Miner { if status.is_success() { let signature_str = json_response["signature"].as_str().ok_or_else(|| { + progress_bar.println(format!("Failed to get signature")); ClientError::from(ClientErrorKind::Custom( "Signature not found in response".to_string(), )) })?; signature = Some(Signature::from_str(signature_str).map_err(|e| { + progress_bar.println(format!("Failed to get parse signature: {}", e)); ClientError::from(ClientErrorKind::Custom(format!( "Invalid signature: {}", e @@ -243,6 +255,11 @@ impl Miner { _ => {} } } + } else { + progress_bar.println(format!( + "Skipping BLXR Endpoint: Signature for confirmation: {:?}", + signature + )); } if let Some(sig) = signature { From 896065ca85f6440a361d32e0a2598dcfc66a76ae Mon Sep 17 00:00:00 2001 From: Lanikean Date: Mon, 26 Aug 2024 13:15:31 -0600 Subject: [PATCH 21/28] refactor jito & fallback submissions, only update hash/balance on success, rm continue on err blxr response --- src/mine.rs | 29 +++++---- src/send_and_confirm_bx.rs | 128 +++++++++++++++++++++++++------------ 2 files changed, 106 insertions(+), 51 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 94f8e1b7..632bad37 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -41,7 +41,6 @@ impl Miner { let mut last_balance = 0; let mut loop_count = 0; loop { - loop_count += 1; println!("Starting mining loop iteration {}", loop_count); // Fetch proof @@ -65,8 +64,6 @@ impl Miner { }, calculate_multiplier(proof.balance, config.top_balance) ); - last_hash_at = proof.last_hash_at; - last_balance = proof.balance; // Calculate cutoff time let cutoff_time = self.get_cutoff(proof, args.buffer_time).await; @@ -108,10 +105,15 @@ impl Miner { .send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget)) .await { - Ok(signature) => println!( - "Transaction submitted successfully. Signature: {}", - signature - ), + Ok(signature) => { + last_hash_at = proof.last_hash_at; + last_balance = proof.balance; + loop_count += 1; + println!( + "Transaction submitted successfully. Signature: {}", + signature + ) + } Err(e) => println!("Error submitting transaction: {:?}", e), } } else { @@ -121,10 +123,15 @@ impl Miner { .send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) .await { - Ok(signature) => println!( - "Transaction submitted successfully. Signature: {}", - signature - ), + Ok(signature) => { + last_hash_at = proof.last_hash_at; + last_balance = proof.balance; + loop_count += 1; + println!( + "Transaction submitted successfully. Signature: {}", + signature + ) + } Err(e) => println!("Error submitting transaction: {:?}", e), } } diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 45cddc6d..f2845cbb 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -1,7 +1,6 @@ use base64::Engine; use chrono::Local; use colored::Colorize; -use futures::TryFutureExt; use ore_api::error::OreError; use serde::Serialize; use serde_json::Value; @@ -17,18 +16,18 @@ use solana_sdk::{ }; use solana_transaction_status::{TransactionConfirmationStatus, UiTransactionEncoding}; use std::str::FromStr; -use std::time::Duration; use crate::{ send_and_confirm::{log_error, log_warning, ComputeBudget}, utils::get_latest_blockhash_with_retries, Miner, }; +use tokio::time::{sleep, Duration}; -const GATEWAY_RETRIES: usize = 50; +const GATEWAY_RETRIES: usize = 150; const GATEWAY_DELAY: u64 = 0; const CONFIRM_DELAY: u64 = 500; -const CONFIRM_RETRIES: usize = 8; +const CONFIRM_RETRIES: usize = 12; const BLOXROUTE_URL: &str = "https://ore-ny.solana.dex.blxrbdn.com/api/v2/mine-ore"; // const BLOXROUTE_URL: &str = "http://localhost:9000/api/v2/mine-ore"; @@ -100,7 +99,6 @@ impl Miner { loop { progress_bar.println(format!("Attempt {} of {}", attempts + 1, GATEWAY_RETRIES)); - progress_bar.println(format!("skip_submit is currently {}", skip_submit)); if attempts > GATEWAY_RETRIES { progress_bar.println("Max gateway retries reached. Exiting send_and_confirm_bx."); return Err(ClientError::from(ClientErrorKind::Custom( @@ -176,26 +174,33 @@ impl Miner { // Submit transaction progress_bar.set_message("Submitting transaction to Bloxroute..."); let client = reqwest::Client::new(); - let response = match client.post(BLOXROUTE_URL).json(&request).send().await { - Ok(response) => response, + + let response = client.post(BLOXROUTE_URL).json(&request).send().await; + + let (status, response_text) = match response { + Ok(response) => { + let status = response.status(); + match response.text().await { + Ok(text) => (status, text), + Err(e) => { + progress_bar.println(format!( + "Failed to get response text: {}. Continuing...", + e + )); + (status, String::from("{}")) + } + } + } Err(e) => { progress_bar - .println(format!("Bloxroute request error: {}. Retrying...", e)); - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); - attempts += 1; - continue; + .println(format!("Bloxroute request error: {}. Continuing...", e)); + ( + reqwest::StatusCode::INTERNAL_SERVER_ERROR, + String::from("{}"), + ) } }; - let status = response.status(); - let response_text = response.text().await.map_err(|e| { - progress_bar.println(format!("Failed to get response text: {}", e)); - ClientError::from(ClientErrorKind::Custom(format!( - "Failed to get response text: {}", - e - ))) - })?; - println!("Response Status: {}", status); println!("Bloxroute Endpoint Response: {}", response_text); @@ -221,38 +226,81 @@ impl Miner { e ))) })?); + skip_submit = true; } else { - match &json_response["code"] { - Value::Number(n) => { + let should_retry_rpc = match &json_response.get("code") { + Some(Value::Number(n)) => { if let Some(code) = n.as_u64() { if code == 6 { progress_bar.println( "Transaction already submitted. Skipping submission...", ); skip_submit = true; + false // Don't retry with RPC if code is 6 } else { - progress_bar.println("Sending via fallback RPC..."); - // attempt to send via RPC client - let send_cfg = RpcSendTransactionConfig { - skip_preflight: true, - preflight_commitment: Some(CommitmentLevel::Confirmed), - encoding: Some(UiTransactionEncoding::Base64), - max_retries: Some(0), - min_context_slot: None, - }; + true // Retry with RPC for any other code + } + } else { + true // Retry with RPC if code is not a u64 + } + } + _ => true, // Retry with RPC if there's no 'code' field or it's not a number + }; + + if should_retry_rpc { + progress_bar.println("Attempting via fallback Jito..."); + // attempt to send via RPC client + let send_cfg = RpcSendTransactionConfig { + skip_preflight: true, + preflight_commitment: Some(CommitmentLevel::Confirmed), + encoding: Some(UiTransactionEncoding::Base64), + max_retries: Some(0), + min_context_slot: None, + }; - self.jito_client + match self + .jito_client + .send_transaction_with_config(&tx, send_cfg) + .await + { + Ok(sig) => { + signature = Some(sig); + skip_submit = true; + progress_bar.println(format!( + "Transaction sent via Jito. Signature: {}", + sig + )); + } + Err(e) => { + progress_bar + .println(format!("Failed to send transaction via Jito: {}", e)); + + // Only try the fallback RPC if we still don't have a signature + if signature.is_none() { + progress_bar.println("Attempting via fallback RPC..."); + match self + .rpc_client .send_transaction_with_config(&tx, send_cfg) - .or_else(|_| { - self.rpc_client - .send_transaction_with_config(&tx, send_cfg) - }) .await - .ok(); + { + Ok(sig) => { + signature = Some(sig); + skip_submit = true; + progress_bar.println(format!( + "Transaction sent via fallback RPC. Signature: {}", + sig + )); + } + Err(e) => { + progress_bar.println(format!( + "Failed to send transaction via fallback RPC: {}", + e + )); + } + } } } } - _ => {} } } } else { @@ -264,7 +312,7 @@ impl Miner { if let Some(sig) = signature { 'confirm: for _ in 0..CONFIRM_RETRIES { - std::thread::sleep(Duration::from_millis(CONFIRM_DELAY)); + sleep(Duration::from_millis(CONFIRM_DELAY)).await; match self.rpc_client.get_signature_statuses(&[sig]).await { Ok(signature_statuses) => { for status in signature_statuses.value { @@ -347,7 +395,7 @@ impl Miner { // If we've exhausted all confirmation retries, continue to the next submission attempt progress_bar.println("Confirmation attempts exhausted. Retrying submission..."); - std::thread::sleep(Duration::from_millis(GATEWAY_DELAY)); + sleep(Duration::from_millis(GATEWAY_DELAY)).await; attempts += 1; } } From 67dcae1107288cee8b79f341794df05f056e73c3 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:30:52 -0600 Subject: [PATCH 22/28] cleanup --- src/mine.rs | 8 -------- src/send_and_confirm_bx.rs | 25 ++----------------------- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 632bad37..8ef4d959 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -41,15 +41,11 @@ impl Miner { let mut last_balance = 0; let mut loop_count = 0; loop { - println!("Starting mining loop iteration {}", loop_count); - // Fetch proof let config = get_config(&self.rpc_client).await; - println!("Fetched config: {:?}", config); let proof = get_updated_proof_with_authority(&self.rpc_client, signer.pubkey(), last_hash_at) .await; - println!("Fetched proof: {:?}", proof); println!( "\n\nStake: {} ORE\n{} Multiplier: {:12}x", @@ -67,10 +63,8 @@ impl Miner { // Calculate cutoff time let cutoff_time = self.get_cutoff(proof, args.buffer_time).await; - println!("Calculated cutoff time: {}", cutoff_time); // Run drillx - println!("Starting hash finding process"); let solution = Self::find_hash_par(proof, cutoff_time, args.cores, config.min_difficulty as u32) .await; @@ -86,9 +80,7 @@ impl Miner { } // Build mine ix - println!("Finding bus"); let bus = self.find_bus().await; - println!("Found bus: {}", bus); ixs.push(ore_api::instruction::mine( signer.pubkey(), signer.pubkey(), diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index f2845cbb..30dda405 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -84,9 +84,6 @@ impl Miner { &tip_pubkey, tip_amount, )); - progress_bar.println(format!(" Additional tip: {} lamports", tip_amount)); - } else { - progress_bar.println(" No additional tip: Priority fee is zero"); } final_ixs.extend_from_slice(ixs); @@ -100,15 +97,12 @@ impl Miner { loop { progress_bar.println(format!("Attempt {} of {}", attempts + 1, GATEWAY_RETRIES)); if attempts > GATEWAY_RETRIES { - progress_bar.println("Max gateway retries reached. Exiting send_and_confirm_bx."); return Err(ClientError::from(ClientErrorKind::Custom( "Max gateway retries reached".into(), ))); } if attempts % 10 == 0 { - progress_bar.println("Resigning transaction and resetting skip_submit"); - // Reset the compute unit price and resign the transaction if self.dynamic_fee { let fee = match self.dynamic_fee().await { Ok(fee) => { @@ -133,7 +127,6 @@ impl Miner { tx = Transaction::new_with_payer(&final_ixs, Some(&fee_payer.pubkey())); } - // Resign the tx let (hash, _slot) = get_latest_blockhash_with_retries(&self.rpc_client).await?; if signer.pubkey() == fee_payer.pubkey() { tx.sign(&[&signer], hash); @@ -141,13 +134,10 @@ impl Miner { tx.sign(&[&signer, &fee_payer], hash); } - // Reset skip_submit flag as we have a new transaction skip_submit = false; } if !skip_submit { - progress_bar.println("Preparing to submit to Bloxroute"); - let tx_data = base64::prelude::BASE64_STANDARD.encode( bincode::serialize(&tx).map_err(|e| { progress_bar.println("Failed to serialize TX"); @@ -158,7 +148,6 @@ impl Miner { })?, ); - // Prepare request let request = PostSubmitRequest { transaction: TransactionMessage { content: tx_data, @@ -171,8 +160,6 @@ impl Miner { fast_best_effort: Some(false), }; - // Submit transaction - progress_bar.set_message("Submitting transaction to Bloxroute..."); let client = reqwest::Client::new(); let response = client.post(BLOXROUTE_URL).json(&request).send().await; @@ -201,8 +188,7 @@ impl Miner { } }; - println!("Response Status: {}", status); - println!("Bloxroute Endpoint Response: {}", response_text); + println!("bloxroute response status: {}", status); let json_response: Value = serde_json::from_str(&response_text).map_err(|e| { progress_bar.println(format!("Failed to get parse reponse json: {}", e)); @@ -248,8 +234,6 @@ impl Miner { }; if should_retry_rpc { - progress_bar.println("Attempting via fallback Jito..."); - // attempt to send via RPC client let send_cfg = RpcSendTransactionConfig { skip_preflight: true, preflight_commitment: Some(CommitmentLevel::Confirmed), @@ -272,12 +256,7 @@ impl Miner { )); } Err(e) => { - progress_bar - .println(format!("Failed to send transaction via Jito: {}", e)); - - // Only try the fallback RPC if we still don't have a signature if signature.is_none() { - progress_bar.println("Attempting via fallback RPC..."); match self .rpc_client .send_transaction_with_config(&tx, send_cfg) @@ -305,7 +284,7 @@ impl Miner { } } else { progress_bar.println(format!( - "Skipping BLXR Endpoint: Signature for confirmation: {:?}", + "Skipping BLXR Endpoint: Active sig: {:?}", signature )); } From b45cbce7ebbbe1905593ecd5cd7dc70e9f85b1d1 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:33:35 -0600 Subject: [PATCH 23/28] cleanup --- src/mine.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 8ef4d959..563965fc 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -88,11 +88,8 @@ impl Miner { solution, )); - println!("Built {} instructions", ixs.len()); - if args.bloxroute { // submit transaction to bloxroute - println!("Submitting transaction to bloxroute"); match self .send_and_confirm_bx(&ixs, ComputeBudget::Fixed(compute_budget)) .await @@ -110,7 +107,6 @@ impl Miner { } } else { // Submit transaction - println!("Submitting transaction to regular RPC"); match self .send_and_confirm(&ixs, ComputeBudget::Fixed(compute_budget), false) .await @@ -127,8 +123,6 @@ impl Miner { Err(e) => println!("Error submitting transaction: {:?}", e), } } - - println!("Completed mining loop iteration {}", loop_count); } } From 21a6ff18f3987e5972e5d2f9cdf91e6a869ffef0 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:34:48 -0600 Subject: [PATCH 24/28] cleanup --- src/mine.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/mine.rs b/src/mine.rs index 563965fc..c03beb0d 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -26,11 +26,8 @@ use crate::{ impl Miner { pub async fn mine(&self, args: MineArgs) { - println!("Starting mining process with args: {:?}", args); - // Open account, if needed. let signer = self.signer(); - println!("Signer public key: {}", signer.pubkey()); self.open().await; // Check num threads @@ -39,7 +36,6 @@ impl Miner { // Start mining loop let mut last_hash_at = 0; let mut last_balance = 0; - let mut loop_count = 0; loop { // Fetch proof let config = get_config(&self.rpc_client).await; @@ -68,14 +64,12 @@ impl Miner { let solution = Self::find_hash_par(proof, cutoff_time, args.cores, config.min_difficulty as u32) .await; - println!("Found solution: {:?}", solution); // Build instruction set let mut ixs = vec![ore_api::instruction::auth(proof_pubkey(signer.pubkey()))]; let mut compute_budget = 500_000; if self.should_reset(config).await && rand::thread_rng().gen_range(0..100).eq(&0) { compute_budget += 100_000; - println!("Adding reset instruction"); ixs.push(ore_api::instruction::reset(signer.pubkey())); } From 367ead3eed00aac9d11313a8bd43bd52ccd6b1af Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:39:27 -0600 Subject: [PATCH 25/28] cleanup --- src/main.rs | 12 ++---------- src/mine.rs | 5 +---- src/send_and_confirm_bx.rs | 4 ++++ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5e70fbd7..71586ab8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,15 +151,7 @@ struct Args { global = true )] jito: bool, - - #[arg( - long, - value_name = "BLOXROUTE", - help = "Use Bloxroute for transaction propegation.", - global = true - )] - bloxroute: bool, - + #[command(subcommand)] command: Commands, } @@ -191,7 +183,7 @@ async fn main() { let tip = Arc::new(RwLock::new(0_u64)); let tip_clone = Arc::clone(&tip); - if args.jito || args.bloxroute { + if args.jito { let url = "ws://bundles-api-rest.jito.wtf/api/v1/bundles/tip_stream"; let (ws_stream, _) = connect_async(url).await.unwrap(); let (_, mut read) = ws_stream.split(); diff --git a/src/mine.rs b/src/mine.rs index c03beb0d..e6f8fdca 100644 --- a/src/mine.rs +++ b/src/mine.rs @@ -74,11 +74,10 @@ impl Miner { } // Build mine ix - let bus = self.find_bus().await; ixs.push(ore_api::instruction::mine( signer.pubkey(), signer.pubkey(), - bus, + self.find_bus().await, solution, )); @@ -91,7 +90,6 @@ impl Miner { Ok(signature) => { last_hash_at = proof.last_hash_at; last_balance = proof.balance; - loop_count += 1; println!( "Transaction submitted successfully. Signature: {}", signature @@ -108,7 +106,6 @@ impl Miner { Ok(signature) => { last_hash_at = proof.last_hash_at; last_balance = proof.balance; - loop_count += 1; println!( "Transaction submitted successfully. Signature: {}", signature diff --git a/src/send_and_confirm_bx.rs b/src/send_and_confirm_bx.rs index 30dda405..df9a7ad0 100644 --- a/src/send_and_confirm_bx.rs +++ b/src/send_and_confirm_bx.rs @@ -277,6 +277,10 @@ impl Miner { )); } } + progress_bar.println(format!( + "Fallback rpc error: {}", + e + )) } } } From b22cd6f3254dcf14c8a6ced06a826dce2bbc2659 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:39:50 -0600 Subject: [PATCH 26/28] cleanup --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 71586ab8..73b70328 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,7 +151,6 @@ struct Args { global = true )] jito: bool, - #[command(subcommand)] command: Commands, } From e4145c6816563eb7eba574ad6eb4c60511bdf128 Mon Sep 17 00:00:00 2001 From: Lanikean Date: Fri, 30 Aug 2024 16:40:48 -0600 Subject: [PATCH 27/28] cleanup --- src/main.rs | 1 + src/utils.rs | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 73b70328..71586ab8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,6 +151,7 @@ struct Args { global = true )] jito: bool, + #[command(subcommand)] command: Commands, } diff --git a/src/utils.rs b/src/utils.rs index 94380c68..a932d2a7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -45,10 +45,6 @@ pub async fn get_updated_proof_with_authority( authority: Pubkey, lash_hash_at: i64, ) -> Proof { - println!( - "Entering get_updated_proof_with_authority. Authority: {}, Last hash at: {}", - authority, lash_hash_at - ); loop { let proof = get_proof_with_authority(client, authority).await; if proof.last_hash_at.gt(&lash_hash_at) { From 678ca47a3cf38f902dfe8c3151f3d07edde671dd Mon Sep 17 00:00:00 2001 From: Lanikean Date: Tue, 3 Sep 2024 20:27:08 -0600 Subject: [PATCH 28/28] add sample command --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 1922c429..e76b4aa0 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,20 @@ To build the codebase from scratch, checkout the repo and use cargo to build: cargo build --release ``` +## Bloxroute + +To run using Trader Api use the following command: + +``` +ore \ + --rpc \ + --priority-fee 30000 \ + --jito mine \ + --cores 8 \ + --bxr \ + --buffer-time 4 +``` + ## Help You can use the `-h` flag on any command to pull up a help menu with documentation: