# SVM Series 04: TransactionBatchProcessor

## What is TransactionBatchProcessor?

The [`TransactionBatchProcessor`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionBatchProcessor.html) handles validation and execution of `sanitized` batched transactions within the SVM acting as the central interface for the whole transaction execution pipeline.

```rust
// TransactionBatchProcessor struct as declared in SVM code
pub struct TransactionBatchProcessor<FG: solana_program_runtime::loaded_programs::ForkGraph> {
    /// Bank slot (i.e. block)
    slot: Slot,

    /// Bank epoch
    epoch: Epoch,

    /// SysvarCache is a collection of system variables that are
    /// accessible from on chain programs. It is passed to SVM from
    /// client code (e.g. Bank) and forwarded to process_message.
    sysvar_cache: RwLock<SysvarCache>,

    /// Programs required for transaction batch processing
    pub program_cache: Arc<RwLock<ProgramCache<FG>>>,

    /// Builtin program ids
    pub builtin_program_ids: RwLock<HashSet<Pubkey>>,

    execution_cost: SVMTransactionExecutionCost,
}
```

## Fields of TransactionBatchProcessor struct

1. `slot` - a fixed timeframe when a validator can produce a block (can be as low as 150ms for alpenglow consensus). It’s Rust data type is a `u64`.
    
2. `epoch` - the timeframe when a leader schedule is valid divided into slots. The leader schedule is the mapping of validator public keys to each slot within the given epoch. It’s Rust data type is also a `u64`.
    
3. `sysvar_cache` - defined by the Rust type [`SysvarCache`](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/sysvar_cache/struct.SysvarCache.html), it contains system variables like the [`Clock`](https://docs.rs/solana-clock/latest/solana_clock/struct.Clock.html) (network time), [`Epoch Schedule`](https://docs.rs/solana-epoch-schedule/latest/solana_epoch_schedule/struct.EpochSchedule.html), [`Epoch Rewards`](https://docs.rs/solana-epoch-rewards/latest/solana_epoch_rewards/struct.EpochRewards.html), [`Rent`](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/__private/struct.Rent.html), [`Stake History`](https://docs.rs/solana-stake-interface/1.2.1/solana_stake_interface/stake_history/struct.StakeHistory.html) and [`Last Network Restart Slot`](https://docs.rs/solana-last-restart-slot/latest/solana_last_restart_slot/struct.LastRestartSlot.html).
    
4. `program_cache` - defined by the Rust type [`ProgramCache`](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/loaded_programs/struct.ProgramCache.html), it contains loaded, compiled and verified programs required for transaction batch processing, optimizing shared data across validator forks. It tracks program information such as usage stats, verification status, and handles deployments, evictions, and tombstones for unloadable programs. Executable programs that are frequently used are kept in memory to improve execution speed through cooperative batch loading and eager preloading. The program cache isn’t saved to disk, so it must be rebuilt after each SVM restart.
    
5. `builtin_program_ids` - It contains builtin program IDs like [`BPF Loader`](https://docs.rs/solana-sdk-ids/latest/solana_sdk_ids/bpf_loader/index.html) that own and execute smart contract programs and program configs like the supported SBF versions (all SBF versions are enabled by default).
    
6. `execution_cost` - configures the CUs used by various operations like how much computing a SHA256 hash costs, cost of logging (`msg!()`), CPI, verifying Ed25519 signatures, CUs used for additional heap allocations above the default and more.
    

## Processing batched sanitized transactions

The method on `TransactionBatchProcessor` for processing sanitized transaction batches is [`TransactionBatchProcessor:: load_and_execute_sanitized_transactions`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionBatchProcessor.html#method.load_and_execute_sanitized_transactions). It acts as the entry point to the SVM and takes the following parameters:

1. `callbacks`: This parameter allows the transaction processor to load information about accounts required for transaction execution. It requires the value supplied to this argument to implement the [`TransactionProcessingCallback`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processing_callback/trait.TransactionProcessingCallback.html) trait which is a supertrait of [`InvokeContextCallback`](https://docs.rs/solana-svm-callback/2.3.7/solana_svm_callback/trait.InvokeContextCallback.html) trait (the callback used by [`solana_program_runtime::invoke_context::InvokeContext`](https://docs.rs/solana-program-runtime/latest/solana_program_runtime/invoke_context/struct.InvokeContext.html) in SVM to manage the main pipeline from runtime to program execution). By defining this trait developers can maintain full control of their application while ensuring integration with SVM according to the specification. This trait has three methods:
    
    * `get_account_shared_data()` which takes `&self`, a public key (the address to fetch information for) as parameters and returns an optional [`AccountSharedData`](https://docs.rs/solana-account/latest/solana_account/struct.AccountSharedData.html) struct which is the in-memory representation of an Account. An `Option::None` can be returned if the account does not exist.
        
    * `account_matches_owner` which takes `&self`, a public key and a slice of public keys (`&[Pubkey]`) representing potential owners of an account. The goal of this method is to get the index of the owner of the `public key` within the slice of owners `&[Pubkey]`, therefore, it returns an `Option` of type `usize`. An `Option::None` can be returned if the `account` public key does not exist in the `Bank` or if the lamports balance is zero.
        
    * `add_builtin_account` which takes a `&self`, `name` of type `&str` and a `program_id` public key. This method is used to add a program to the available programs in the execution pipeline, for example adding the `native loader` to the bank, that would load a smart contract program into the execution pipeline.
        
2. `sanitized_txs`: This parameter contains a slice of sanitized Solana transactions (`&[impl SVMTransaction]`). A sanitized Solana transaction can be any Rust type as long as it implements the [`SVMTransaction`](https://docs.rs/solana-svm-transaction/latest/solana_svm_transaction/svm_transaction/trait.SVMTransaction.html) trait which is a supertrait of [`SVMMessage`](https://docs.rs/solana-svm-transaction/latest/solana_svm_transaction/svm_message/trait.SVMMessage.html). These traits allow any type implementing them to provide convenience methods that can fetch information such as the fee payer, the first signature, all the signatures in a transaction, number of transaction signatures, the recent blockhash of the transaction, the number of write locks, the account keys and more. An example of a type implementing this trait is [`SanitizedTransaction`](https://docs.rs/solana-transaction/latest/solana_transaction/sanitized/struct.SanitizedTransaction.html).
    
3. `check_results` - this parameter contains a list of the results of checking the [validity of a transaction](https://docs.rs/solana-svm/latest/solana_svm/account_loader/type.TransactionCheckResult.html). Some checks performed that produce these results include the validity of a blockhash or nonce, whether an account matches it’s owner and whether the number of sanitized transactions equals the number of transactions that underwent these checks.
    
4. `environment` - This parameter is the runtime environment for transaction batch processing instantiated by [`TransactionProcessingEnvironment`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionProcessingEnvironment.html) struct. It configures the blockhash to use for the current transaction batch, [determine rent due for the account and collect rent](https://docs.rs/solana-svm-rent-collector/latest/solana_svm_rent_collector/svm_rent_collector/trait.SVMRentCollector.html), the [runtime features](https://docs.rs/solana-svm-feature-set/latest/solana_svm_feature_set/struct.SVMFeatureSet.html) to use, lamports per signature for nonce accounts and the total stake for the current epoch.
    
5. `config` - this parameter configures customization of transaction processing behavior using [`TransactionProcessingConfig`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionProcessingConfig.html) struct. Custom configurations include [account overrides](https://docs.rs/solana-svm/latest/solana_svm/account_overrides/struct.AccountOverrides.html), log message byte size limits, configuring of the [recording capabilities](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.ExecutionRecordingConfig.html) for transaction execution, whether to limit the number of programs loaded for the transaction batch and whether or not to check a program’s modification slot when replenishing a program cache instance.
    

The [`load_and_execute_sanitized_transactions`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionBatchProcessor.html#method.load_and_execute_sanitized_transactions) returns a [`LoadAndExecuteSanitizedTransactionsOutput`](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.LoadAndExecuteSanitizedTransactionsOutput.html) struct which contains the fields:

1. `error_metrics` - the [error metrics](https://docs.rs/solana-svm/latest/solana_svm/transaction_error_metrics/struct.TransactionErrorMetrics.html) for the processed transactions
    
2. `execute_timings` - [timings for transaction batch execution](https://docs.rs/solana-timings/2.3.7/solana_timings/struct.ExecuteTimings.html)
    
3. `processing_results` - a vector containing type alias [TransactionProcessingResult](https://docs.rs/solana-svm/latest/solana_svm/transaction_processing_result/type.TransactionProcessingResult.html) indicating whether a transaction executed successfully or the transaction execution failed and needs to be rolled back
    
4. `balance_collector` - a `Option<`[`BalanceCollector`](https://docs.rs/solana-svm/latest/solana_svm/transaction_balances/struct.BalanceCollector.html)`>` containing balances accumulated for [`TransactionStatusSender`](https://docs.rs/solana-ledger/latest/solana_ledger/blockstore_processor/struct.TransactionStatusSender.html) (a channel within the Solana ledger) when transaction balance recording is enabled.
    

## ForkGraph Trait

The struct `TransactionBatchProcessor` contains a generic `FG` which requires the passed type to implement the [`ForkGraph`](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/loaded_programs/trait.ForkGraph.html) trait. The trait maps the block’s relationship between two slots returning the [BlockRelation enum](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/loaded_programs/enum.BlockRelation.html).

```rust
// Relationship between two fork IDs
pub enum BlockRelation {
    // The slot is on the same fork and is an ancestor of the other slot
    Ancestor,
    // The two slots are equal and are on the same fork
    Equal,
    // The slot is on the same fork and is a descendant of the other slot
    Descendant,
    // The slots are on two different forks and may have had a common ancestor at some point
    Unrelated,
    // Either one or both of the slots are either older than the latest root, or are in future
    Unknown,
}
```

The `ForkGraph` trait requires the [`relationship(&self, a: Slot, b: Slot)`](https://docs.rs/solana-program-runtime/2.3.7/solana_program_runtime/loaded_programs/trait.ForkGraph.html#tymethod.relationship) method to be implemented for the generic type. This method requires the two slots arguments `a: Slot` and `b: Slot` to be compared in a manner that returns the relationship (`BlockRelation` enum) between them. The `Slot` is just a type alias for a Rust `u64` representing an [entry](https://solana.com/docs/references/terminology#entry) that estimates wallclock duration (a `tick`) . An example of implementing this trait:

```bash
# Add `solana-clock` dependency used in SVM ecosystem, it contains the `Slot` type
cargo add solana-clock
```

```rust
pub struct SlotRelationships;

impl ForkGraph for SlotRelationships {
    fn relationship(&self, slot_a: Slot, slot_b: Slot) -> BlockRelation {
        // Since a `Slot` is just a Rust `u64`, and a `u64` implement
        // Rust `PartialCmp` and `Cmp`, we can use `.cmp()` method
        // on `slot_a` to compare against `slot_b` and derive a relationship
        // checking if `slot_a` is less than, equal to or greater than `slot_b`
        match slot_a.cmp(&slot_b) {
            std::cmp::Ordering::Less => BlockRelation::Ancestor,
            std::cmp::Ordering::Equal => BlockRelation::Equal,
            std::cmp::Ordering::Greater => BlockRelation::Descendant,
        }
    }
}
```

The `TransactionBatchProcessor` has some more methods to configure of get information about the transaction execution pipeline that you can [explore](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionBatchProcessor.html#method.reset_sysvar_cache).

[&lt; Previous Article: SVM Series 03: Compute Budget & Syscalls](https://448.africa/svm-series-03-compute-budget-and-syscalls)

## Resources

1. Understanding Slots, Blocks, and Epochs on Solana  
    [https://www.helius.dev/blog/solana-slots-blocks-and-epochs](https://www.helius.dev/blog/solana-slots-blocks-and-epochs)
    
2. Solana SVM TransactionBatchProcessor module docs  
    [https://docs.rs/solana-svm/latest/solana\_svm/transaction\_processor/struct.TransactionBatchProcessor.html](https://docs.rs/solana-svm/latest/solana_svm/transaction_processor/struct.TransactionBatchProcessor.html)
