From d94ae11ed3ac8ae926bd9b287fce0c27897ec3c2 Mon Sep 17 00:00:00 2001 From: Sergey Timoshin Date: Sat, 12 Apr 2025 14:05:44 +0100 Subject: [PATCH] add support for custom account compression program ID --- .../parser/merkle_tree_events_parser.rs | 4 ++-- src/ingester/parser/mod.rs | 18 ++++++++++++++++-- src/ingester/parser/tx_event_parser.rs | 4 ++-- src/main.rs | 11 +++++++++++ src/snapshot/mod.rs | 9 ++++----- 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/ingester/parser/merkle_tree_events_parser.rs b/src/ingester/parser/merkle_tree_events_parser.rs index 4ab77013..19159d2c 100644 --- a/src/ingester/parser/merkle_tree_events_parser.rs +++ b/src/ingester/parser/merkle_tree_events_parser.rs @@ -7,7 +7,7 @@ use crate::ingester::parser::indexer_events::{ use crate::ingester::parser::state_update::{ IndexedTreeLeafUpdate, LeafNullification, StateUpdate, }; -use crate::ingester::parser::{ACCOUNT_COMPRESSION_PROGRAM_ID, NOOP_PROGRAM_ID}; +use crate::ingester::parser::{get_compression_program_id, NOOP_PROGRAM_ID}; use crate::ingester::typedefs::block_info::{Instruction, TransactionInfo}; use borsh::BorshDeserialize; use solana_program::pubkey::Pubkey; @@ -20,7 +20,7 @@ pub fn parse_merkle_tree_event( next_instruction: &Instruction, tx: &TransactionInfo, ) -> Result, IngesterError> { - if ACCOUNT_COMPRESSION_PROGRAM_ID == instruction.program_id + if get_compression_program_id() == instruction.program_id && next_instruction.program_id == NOOP_PROGRAM_ID && tx.error.is_none() { diff --git a/src/ingester/parser/mod.rs b/src/ingester/parser/mod.rs index 9ea3c8a5..dc9317b7 100644 --- a/src/ingester/parser/mod.rs +++ b/src/ingester/parser/mod.rs @@ -1,5 +1,6 @@ use merkle_tree_events_parser::parse_merkle_tree_event; use solana_sdk::pubkey::Pubkey; +use std::sync::OnceLock; use tx_event_parser::parse_legacy_public_transaction_event; use tx_event_parser_v2::create_state_update_v2; @@ -17,8 +18,21 @@ pub mod tx_event_parser_v2; use crate::ingester::parser::tx_event_parser_v2::parse_public_transaction_event_v2; use solana_program::pubkey; -pub const ACCOUNT_COMPRESSION_PROGRAM_ID: Pubkey = - pubkey!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"); +static ACCOUNT_COMPRESSION_PROGRAM_ID: OnceLock = OnceLock::new(); +pub fn get_compression_program_id() -> Pubkey { + *ACCOUNT_COMPRESSION_PROGRAM_ID + .get_or_init(|| pubkey!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq")) +} +pub fn set_compression_program_id(program_id_str: &str) -> Result<(), String> { + match program_id_str.parse::() { + Ok(pubkey) => match ACCOUNT_COMPRESSION_PROGRAM_ID.set(pubkey) { + Ok(_) => Ok(()), + Err(_) => Err("Compression program ID has already been set".to_string()), + }, + Err(err) => Err(format!("Invalid compression program ID: {}", err)), + } +} + const SYSTEM_PROGRAM: Pubkey = pubkey!("11111111111111111111111111111111"); const NOOP_PROGRAM_ID: Pubkey = pubkey!("noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV"); const VOTE_PROGRAM_ID: Pubkey = pubkey!("Vote111111111111111111111111111111111111111"); diff --git a/src/ingester/parser/tx_event_parser.rs b/src/ingester/parser/tx_event_parser.rs index d4287a3d..f1e689f2 100644 --- a/src/ingester/parser/tx_event_parser.rs +++ b/src/ingester/parser/tx_event_parser.rs @@ -3,7 +3,7 @@ use crate::ingester::error::IngesterError; use crate::ingester::parser::indexer_events::PublicTransactionEventV1; use crate::ingester::parser::state_update::{AccountTransaction, StateUpdate}; use crate::ingester::parser::tree_info::TreeInfo; -use crate::ingester::parser::{ACCOUNT_COMPRESSION_PROGRAM_ID, NOOP_PROGRAM_ID, SYSTEM_PROGRAM}; +use crate::ingester::parser::{get_compression_program_id, NOOP_PROGRAM_ID, SYSTEM_PROGRAM}; use crate::ingester::typedefs::block_info::{Instruction, TransactionInfo}; use anchor_lang::AnchorDeserialize; use light_compressed_account::TreeType; @@ -18,7 +18,7 @@ pub fn parse_legacy_public_transaction_event( next_instruction: &Instruction, next_next_instruction: &Instruction, ) -> Result, IngesterError> { - if ACCOUNT_COMPRESSION_PROGRAM_ID == instruction.program_id + if get_compression_program_id() == instruction.program_id && next_instruction.program_id == SYSTEM_PROGRAM && next_next_instruction.program_id == NOOP_PROGRAM_ID && tx.error.is_none() diff --git a/src/main.rs b/src/main.rs index 80bbae4b..185013ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,6 +90,10 @@ struct Args { #[arg(long, action = clap::ArgAction::SetTrue)] disable_api: bool, + /// Custom account compression program ID (optional) + #[arg(long, default_value = "compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq")] + compression_program_id: String, + /// Metrics endpoint in the format `host:port` /// If provided, metrics will be sent to the specified statsd server. #[arg(long, default_value = None)] @@ -190,6 +194,13 @@ async fn main() { setup_logging(args.logging_format); setup_metrics(args.metrics_endpoint); + if let Err(err) = + photon_indexer::ingester::parser::set_compression_program_id(&args.compression_program_id) + { + error!("Failed to set compression program ID: {}", err); + std::process::exit(1); + } + let db_conn = setup_database_connection(args.db_url.clone(), args.max_db_conn).await; if args.db_url.is_none() { info!("Running migrations..."); diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index 32cfe95f..ee669507 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -11,9 +11,9 @@ use std::{ pub use crate::common::{ fetch_block_parent_slot, get_network_start_slot, setup_logging, setup_metrics, LoggingFormat, }; +use crate::ingester::parser::get_compression_program_id; use crate::ingester::{ fetchers::BlockStreamConfig, - parser::ACCOUNT_COMPRESSION_PROGRAM_ID, typedefs::block_info::{BlockInfo, Instruction, TransactionInfo}, }; use anyhow::{anyhow, Context as AnyhowContext, Result}; @@ -27,6 +27,7 @@ use s3::region::Region; use s3::{bucket::Bucket, BucketConfiguration}; use s3_utils::multipart_upload::put_object_stream_custom; use tokio::io::{AsyncRead, ReadBuf}; + pub mod s3_utils; pub const MEGABYTE: usize = 1024 * 1024; @@ -356,10 +357,8 @@ impl DirectoryAdapter { } fn is_compression_instruction(instruction: &Instruction) -> bool { - instruction.program_id == ACCOUNT_COMPRESSION_PROGRAM_ID - || instruction - .accounts - .contains(&ACCOUNT_COMPRESSION_PROGRAM_ID) + instruction.program_id == get_compression_program_id() + || instruction.accounts.contains(&get_compression_program_id()) } pub fn is_compression_transaction(tx: &TransactionInfo) -> bool {