From 9a8b84e1a9e0713cb7f7b54a4d674e74025c5e4b Mon Sep 17 00:00:00 2001 From: ananas Date: Thu, 24 Jul 2025 00:00:40 +0100 Subject: [PATCH 1/2] chore: add get signatures xtask --- xtask/src/get_signatures.rs | 81 +++++++++++++++++++++++++++++++++++++ xtask/src/main.rs | 5 +++ 2 files changed, 86 insertions(+) create mode 100644 xtask/src/get_signatures.rs diff --git a/xtask/src/get_signatures.rs b/xtask/src/get_signatures.rs new file mode 100644 index 0000000000..d9b1c706b9 --- /dev/null +++ b/xtask/src/get_signatures.rs @@ -0,0 +1,81 @@ +use anyhow::Result; +use clap::Parser; +use solana_client::rpc_client::GetConfirmedSignaturesForAddress2Config; +use solana_client::rpc_client::RpcClient; +use solana_sdk::signature::Signature; +use std::str::FromStr; + +#[derive(Parser)] +pub struct Options { + /// RPC URL to connect to + #[clap(long, default_value = "https://api.devnet.solana.com")] + pub rpc_url: String, + + /// Start searching backwards from this transaction signature + #[clap(long)] + pub before: Option, + + /// Search forward until this transaction signature + #[clap(long)] + pub until: Option, + + /// Maximum number of signatures to return (default: 1000, max: 1000) + #[clap(long, default_value = "100")] + pub limit: usize, +} + +pub async fn get_signatures(options: Options) -> Result<()> { + println!("Connecting to RPC: {}", options.rpc_url); + + let client = RpcClient::new(options.rpc_url); + + let mut config = GetConfirmedSignaturesForAddress2Config { + before: None, + until: None, + limit: Some(options.limit.min(1000)), // Cap at Solana's max limit + commitment: None, + }; + + // Parse before signature if provided + if let Some(before_str) = options.before { + let before_sig = Signature::from_str(&before_str)?; + config.before = Some(before_sig); + println!("Searching before signature: {}", before_sig); + } + + // Parse until signature if provided + if let Some(until_str) = options.until { + let until_sig = Signature::from_str(&until_str)?; + config.until = Some(until_sig); + println!("Searching until signature: {}", until_sig); + } + + let signatures = + client.get_signatures_for_address_with_config(&account_compression::ID, config)?; + + println!("\nFound {} signatures:", signatures.len()); + println!( + "{:<88} {:<10} {:<10} {}", + "Signature", "Slot", "Block Time", "Error" + ); + println!("{}", "-".repeat(120)); + + for sig_info in signatures { + let block_time = sig_info + .block_time + .map(|t| t.to_string()) + .unwrap_or_else(|| "unknown".to_string()); + + let error = sig_info + .err + .map(|e| format!("{:?}", e)) + .unwrap_or_else(|| "none".to_string()); + + println!( + "{:<88} {:<10} {:<10} {}", + sig_info.signature, sig_info.slot, block_time, error + ); + } + + Ok(()) +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index df08d63a57..35c697bd15 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -8,6 +8,7 @@ mod create_update_protocol_config_ix; mod create_vkeyrs_from_gnark_key; mod export_photon_test_data; mod fee; +mod get_signatures; mod hash_set; mod new_deployment; mod type_sizes; @@ -57,6 +58,9 @@ enum Command { InitNewDeployment(new_deployment::Options), /// cargo xtask create-update-protocol-config --slot-length CreateUpdateProtocolConfigIx(create_update_protocol_config_ix::Options), + /// Get signatures for the Light System Program ID + /// Example: cargo xtask get-signatures --rpc-url https://api.devnet.solana.com --before --until --limit 50 + GetSignatures(get_signatures::Options), } #[tokio::main] @@ -89,5 +93,6 @@ async fn main() -> Result<(), anyhow::Error> { Command::CreateUpdateProtocolConfigIx(opts) => { create_update_protocol_config_ix::create_update_protocol_config_ix(opts).await } + Command::GetSignatures(opts) => get_signatures::get_signatures(opts).await, } } From 0ef6c699a4f5a4ff897acd2c5db50babc7d29341 Mon Sep 17 00:00:00 2001 From: ananas Date: Thu, 24 Jul 2025 00:38:48 +0100 Subject: [PATCH 2/2] add slot search --- xtask/src/get_signatures.rs | 116 +++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 40 deletions(-) diff --git a/xtask/src/get_signatures.rs b/xtask/src/get_signatures.rs index d9b1c706b9..384e808afb 100644 --- a/xtask/src/get_signatures.rs +++ b/xtask/src/get_signatures.rs @@ -3,7 +3,10 @@ use clap::Parser; use solana_client::rpc_client::GetConfirmedSignaturesForAddress2Config; use solana_client::rpc_client::RpcClient; use solana_sdk::signature::Signature; +use std::fs::File; +use std::io::Write; use std::str::FromStr; +use std::u64; #[derive(Parser)] pub struct Options { @@ -18,9 +21,14 @@ pub struct Options { /// Search forward until this transaction signature #[clap(long)] pub until: Option, - + /// Search forward until this transaction signature + #[clap(long)] + pub until_slot: Option, + /// Search forward until this transaction signature + #[clap(long)] + pub before_slot: Option, /// Maximum number of signatures to return (default: 1000, max: 1000) - #[clap(long, default_value = "100")] + #[clap(long, default_value = "1000")] pub limit: usize, } @@ -29,53 +37,81 @@ pub async fn get_signatures(options: Options) -> Result<()> { let client = RpcClient::new(options.rpc_url); - let mut config = GetConfirmedSignaturesForAddress2Config { - before: None, - until: None, - limit: Some(options.limit.min(1000)), // Cap at Solana's max limit - commitment: None, - }; + // Create target directory and file + std::fs::create_dir_all("target")?; + let mut file = File::create("target/signatures.txt")?; - // Parse before signature if provided - if let Some(before_str) = options.before { - let before_sig = Signature::from_str(&before_str)?; - config.before = Some(before_sig); - println!("Searching before signature: {}", before_sig); - } + let mut latest_slot = u64::MAX; + let mut before = None; + let target_until_slot = options.until_slot.unwrap_or(0); + let target_before_slot = options.before_slot.unwrap_or(u64::MAX); - // Parse until signature if provided - if let Some(until_str) = options.until { - let until_sig = Signature::from_str(&until_str)?; - config.until = Some(until_sig); - println!("Searching until signature: {}", until_sig); - } + while latest_slot > target_until_slot { + let config = GetConfirmedSignaturesForAddress2Config { + before, + until: None, + limit: Some(options.limit.min(1000)), // Cap at Solana's max limit + commitment: None, + }; + let signatures = + client.get_signatures_for_address_with_config(&account_compression::ID, config)?; - let signatures = - client.get_signatures_for_address_with_config(&account_compression::ID, config)?; + println!("\nFound {} signatures:", signatures.len()); + println!( + "{:<88} {:<10} {:<10} {}", + "Signature", "Slot", "Block Time", "Error" + ); + println!("{}", "-".repeat(120)); - println!("\nFound {} signatures:", signatures.len()); - println!( - "{:<88} {:<10} {:<10} {}", - "Signature", "Slot", "Block Time", "Error" - ); - println!("{}", "-".repeat(120)); + for sig_info in signatures.iter() { + let slot = sig_info.slot; - for sig_info in signatures { - let block_time = sig_info - .block_time - .map(|t| t.to_string()) - .unwrap_or_else(|| "unknown".to_string()); + if slot > target_before_slot { + continue; + } + if slot < target_until_slot { + continue; + } + if sig_info.err.is_some() { + continue; + } + + // Write signature to file + writeln!(file, "{}", sig_info.signature)?; + + let block_time = sig_info + .block_time + .map(|t| t.to_string()) + .unwrap_or_else(|| "unknown".to_string()); - let error = sig_info - .err - .map(|e| format!("{:?}", e)) - .unwrap_or_else(|| "none".to_string()); + let error = sig_info + .err + .as_ref() + .map(|e| format!("{:?}", e)) + .unwrap_or_else(|| "none".to_string()); + println!( + "{:<88} {:<10} {:<10} {}", + sig_info.signature, sig_info.slot, block_time, error + ); + } + before = signatures + .last() + .map(|sig| Signature::from_str(&sig.signature).unwrap()); + + latest_slot = signatures.last().map(|sig| sig.slot).unwrap_or(u64::MAX); + println!("latest slot {}", latest_slot); println!( - "{:<88} {:<10} {:<10} {}", - sig_info.signature, sig_info.slot, block_time, error + "until target slot {}", + latest_slot.saturating_sub(target_until_slot) ); + if latest_slot < options.until_slot.unwrap() { + println!( + "Reached the specified slot {} {}", + latest_slot, + options.until_slot.unwrap() + ); + } } - Ok(()) }