From cbb8b79a60009abe3064410c4ede976f1c406c8f Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Mon, 1 Feb 2021 14:00:51 -0700 Subject: [PATCH] Add validator flag to opt in to cpi and logs storage (#14922) * Add validator flag to opt in to cpi and logs storage * Default TestValidator to opt-in; allow using in multinode-demo * No clone Co-authored-by: Carl Lin --- core/src/banking_stage.rs | 9 +++-- core/src/replay_stage.rs | 5 ++- core/src/rpc.rs | 1 + core/src/transaction_status_service.rs | 18 +++++++-- core/src/validator.rs | 12 +++++- ledger/src/blockstore_processor.rs | 43 ++++++++++++++-------- multinode-demo/bootstrap-validator.sh | 3 ++ multinode-demo/validator.sh | 3 ++ run.sh | 1 + validator/src/bin/solana-test-validator.rs | 1 + validator/src/main.rs | 9 +++++ 11 files changed, 81 insertions(+), 24 deletions(-) diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index a7d80c607f..f333caa5dd 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -593,7 +593,7 @@ impl BankingStage { ); bank_utils::find_and_send_votes(txs, &tx_results, Some(gossip_vote_sender)); - if let Some(sender) = transaction_status_sender { + if let Some(transaction_status_sender) = transaction_status_sender { let post_balances = bank.collect_balances(batch); let post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals); send_transaction_status_batch( @@ -605,7 +605,7 @@ impl BankingStage { TransactionTokenBalancesSet::new(pre_token_balances, post_token_balances), inner_instructions, transaction_logs, - sender, + transaction_status_sender, ); } } @@ -2074,7 +2074,10 @@ mod tests { &transactions, &poh_recorder, 0, - Some(transaction_status_sender), + Some(TransactionStatusSender { + sender: transaction_status_sender, + enable_cpi_and_log_storage: false, + }), &gossip_vote_sender, ); diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 29aed9fd36..942a62ba57 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -2746,7 +2746,10 @@ pub(crate) mod tests { &bank, &entries, true, - Some(transaction_status_sender), + Some(TransactionStatusSender { + sender: transaction_status_sender, + enable_cpi_and_log_storage: false, + }), Some(&replay_vote_sender), ); diff --git a/core/src/rpc.rs b/core/src/rpc.rs index bd5a0c3143..f063ad97db 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -109,6 +109,7 @@ pub struct JsonRpcConfig { pub enable_validator_exit: bool, pub enable_set_log_filter: bool, pub enable_rpc_transaction_history: bool, + pub enable_cpi_and_log_storage: bool, pub identity_pubkey: Pubkey, pub faucet_addr: Option, pub health_check_slot_distance: u64, diff --git a/core/src/transaction_status_service.rs b/core/src/transaction_status_service.rs index 0a6115dc15..620ab76ce6 100644 --- a/core/src/transaction_status_service.rs +++ b/core/src/transaction_status_service.rs @@ -2,7 +2,7 @@ use crossbeam_channel::{Receiver, RecvTimeoutError}; use itertools::izip; use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusBatch}; use solana_runtime::{ - bank::{Bank, NonceRollbackInfo}, + bank::{Bank, InnerInstructionsList, NonceRollbackInfo, TransactionLogMessages}, transaction_utils::OrderedIterator, }; use solana_transaction_status::{InnerInstructions, TransactionStatusMeta}; @@ -60,6 +60,18 @@ impl TransactionStatusService { } = write_transaction_status_receiver.recv_timeout(Duration::from_secs(1))?; let slot = bank.slot(); + let inner_instructions_iter: Box>> = + if let Some(inner_instructions) = inner_instructions { + Box::new(inner_instructions.into_iter()) + } else { + Box::new(std::iter::repeat_with(|| None)) + }; + let transaction_logs_iter: Box> = + if let Some(transaction_logs) = transaction_logs { + Box::new(transaction_logs.into_iter()) + } else { + Box::new(std::iter::repeat_with(Vec::new)) + }; for ( (_, transaction), (status, nonce_rollback), @@ -76,8 +88,8 @@ impl TransactionStatusService { balances.post_balances, token_balances.pre_token_balances, token_balances.post_token_balances, - inner_instructions, - transaction_logs + inner_instructions_iter, + transaction_logs_iter ) { if Bank::can_commit(&status) && !transaction.signatures.is_empty() { let fee_calculator = nonce_rollback diff --git a/core/src/validator.rs b/core/src/validator.rs index e92e3734f1..8b182a5ae9 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -984,7 +984,11 @@ fn new_banks_from_ledger( let blockstore = Arc::new(blockstore); let transaction_history_services = if config.rpc_addrs.is_some() && config.rpc_config.enable_rpc_transaction_history { - initialize_rpc_transaction_history_services(blockstore.clone(), exit) + initialize_rpc_transaction_history_services( + blockstore.clone(), + exit, + config.rpc_config.enable_cpi_and_log_storage, + ) } else { TransactionHistoryServices::default() }; @@ -1153,9 +1157,13 @@ fn backup_and_clear_blockstore(ledger_path: &Path, start_slot: Slot, shred_versi fn initialize_rpc_transaction_history_services( blockstore: Arc, exit: &Arc, + enable_cpi_and_log_storage: bool, ) -> TransactionHistoryServices { let (transaction_status_sender, transaction_status_receiver) = unbounded(); - let transaction_status_sender = Some(transaction_status_sender); + let transaction_status_sender = Some(TransactionStatusSender { + sender: transaction_status_sender, + enable_cpi_and_log_storage, + }); let transaction_status_service = Some(TransactionStatusService::new( transaction_status_receiver, blockstore.clone(), diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 782446466c..06816e2341 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -136,7 +136,7 @@ fn execute_batch( .. } = tx_results; - if let Some(sender) = transaction_status_sender { + if let Some(transaction_status_sender) = transaction_status_sender { let post_token_balances = if record_token_balances { collect_token_balances(&bank, &batch, &mut mint_decimals) } else { @@ -155,7 +155,7 @@ fn execute_batch( token_balances, inner_instructions, transaction_logs, - sender, + transaction_status_sender, ); } @@ -1093,11 +1093,15 @@ pub struct TransactionStatusBatch { pub statuses: Vec, pub balances: TransactionBalancesSet, pub token_balances: TransactionTokenBalancesSet, - pub inner_instructions: Vec>, - pub transaction_logs: Vec, + pub inner_instructions: Option>>, + pub transaction_logs: Option>, } -pub type TransactionStatusSender = Sender; +#[derive(Clone)] +pub struct TransactionStatusSender { + pub sender: Sender, + pub enable_cpi_and_log_storage: bool, +} pub fn send_transaction_status_batch( bank: Arc, @@ -1111,16 +1115,25 @@ pub fn send_transaction_status_batch( transaction_status_sender: TransactionStatusSender, ) { let slot = bank.slot(); - if let Err(e) = transaction_status_sender.send(TransactionStatusBatch { - bank, - transactions: transactions.to_vec(), - iteration_order, - statuses, - balances, - token_balances, - inner_instructions, - transaction_logs, - }) { + let (inner_instructions, transaction_logs) = + if !transaction_status_sender.enable_cpi_and_log_storage { + (None, None) + } else { + (Some(inner_instructions), Some(transaction_logs)) + }; + if let Err(e) = transaction_status_sender + .sender + .send(TransactionStatusBatch { + bank, + transactions: transactions.to_vec(), + iteration_order, + statuses, + balances, + token_balances, + inner_instructions, + transaction_logs, + }) + { trace!( "Slot {} transaction_status send batch failed: {:?}", slot, diff --git a/multinode-demo/bootstrap-validator.sh b/multinode-demo/bootstrap-validator.sh index d938211890..fc269ffd24 100755 --- a/multinode-demo/bootstrap-validator.sh +++ b/multinode-demo/bootstrap-validator.sh @@ -48,6 +48,9 @@ while [[ -n $1 ]]; do elif [[ $1 = --enable-rpc-transaction-history ]]; then args+=("$1") shift + elif [[ $1 = --enable-cpi-and-log-storage ]]; then + args+=("$1") + shift elif [[ $1 = --enable-rpc-bigtable-ledger-storage ]]; then args+=("$1") shift diff --git a/multinode-demo/validator.sh b/multinode-demo/validator.sh index 512b36aae9..6eabd92b60 100755 --- a/multinode-demo/validator.sh +++ b/multinode-demo/validator.sh @@ -130,6 +130,9 @@ while [[ -n $1 ]]; do elif [[ $1 = --enable-rpc-transaction-history ]]; then args+=("$1") shift + elif [[ $1 = --enable-cpi-and-log-storage ]]; then + args+=("$1") + shift elif [[ $1 = --skip-poh-verify ]]; then args+=("$1") shift diff --git a/run.sh b/run.sh index 7833a84565..6e503b458d 100755 --- a/run.sh +++ b/run.sh @@ -102,6 +102,7 @@ args=( --log - --enable-rpc-exit --enable-rpc-transaction-history + --enable-cpi-and-log-storage --init-complete-file "$dataDir"/init-completed --snapshot-compression none --require-tower diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index 1d09b3187a..da0c3f2281 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -376,6 +376,7 @@ fn main() { .rpc_config(JsonRpcConfig { enable_validator_exit: true, enable_rpc_transaction_history: true, + enable_cpi_and_log_storage: false, faucet_addr, ..JsonRpcConfig::default() }) diff --git a/validator/src/main.rs b/validator/src/main.rs index 683fbddb39..80a9be57ec 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -957,6 +957,14 @@ pub fn main() { .takes_value(false) .help("Upload new confirmed blocks into a BigTable instance"), ) + .arg( + Arg::with_name("enable_cpi_and_log_storage") + .long("enable-cpi-and-log-storage") + .requires("enable_rpc_transaction_history") + .takes_value(false) + .help("Include CPI inner instructions and logs in the \ + historical transaction info stored"), + ) .arg( Arg::with_name("rpc_max_multiple_accounts") .long("rpc-max-multiple-accounts") @@ -1533,6 +1541,7 @@ pub fn main() { enable_validator_exit: matches.is_present("enable_rpc_exit"), enable_set_log_filter: matches.is_present("enable_rpc_set_log_filter"), enable_rpc_transaction_history: matches.is_present("enable_rpc_transaction_history"), + enable_cpi_and_log_storage: matches.is_present("enable_cpi_and_log_storage"), enable_bigtable_ledger_storage: matches .is_present("enable_rpc_bigtable_ledger_storage"), enable_bigtable_ledger_upload: matches.is_present("enable_bigtable_ledger_upload"),