photon_indexer/ingester/parser/
state_update.rs

1use std::collections::{HashMap, HashSet};
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use solana_sdk::pubkey::Pubkey;
5use solana_sdk::signature::Signature;
6
7use crate::common::typedefs::account::Account;
8
9use crate::common::typedefs::hash::Hash;
10
11use super::indexer_events::RawIndexedElement;
12
13#[derive(BorshDeserialize, BorshSerialize, Debug, Clone, PartialEq, Eq)]
14pub struct PathNode {
15    pub node: [u8; 32],
16    pub index: u32,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct EnrichedPathNode {
21    pub node: PathNode,
22    pub slot: u64,
23    pub tree: [u8; 32],
24    pub seq: u64,
25    pub level: usize,
26    pub tree_depth: usize,
27    pub leaf_index: Option<u32>,
28}
29
30pub struct PathUpdate {
31    pub tree: [u8; 32],
32    pub path: Vec<PathNode>,
33    pub seq: u64,
34}
35
36#[derive(Hash, Eq, Clone, PartialEq, Debug)]
37pub struct Transaction {
38    pub signature: Signature,
39    pub slot: u64,
40    pub uses_compression: bool,
41    pub error: Option<String>,
42}
43
44#[derive(Hash, PartialEq, Eq, Debug, Clone)]
45pub struct AccountTransaction {
46    pub hash: Hash,
47    pub signature: Signature,
48}
49
50#[derive(Hash, PartialEq, Eq, Debug, Clone)]
51pub struct LeafNullification {
52    pub tree: Pubkey,
53    pub leaf_index: u64,
54    pub seq: u64,
55    pub signature: Signature,
56}
57
58#[derive(PartialEq, Eq, Debug, Clone)]
59pub struct IndexedTreeLeafUpdate {
60    pub tree: Pubkey,
61    pub leaf: RawIndexedElement,
62    pub hash: [u8; 32],
63    pub seq: u64,
64}
65
66#[derive(Default, Debug, Clone, PartialEq, Eq)]
67/// Representation of state update of the compression system that is optimal for simple persistance.
68pub struct StateUpdate {
69    pub in_accounts: HashSet<Hash>,
70    pub out_accounts: Vec<Account>,
71    pub account_transactions: HashSet<AccountTransaction>,
72    pub transactions: HashSet<Transaction>,
73    pub leaf_nullifications: HashSet<LeafNullification>,
74    pub indexed_merkle_tree_updates: HashMap<(Pubkey, u64), IndexedTreeLeafUpdate>,
75}
76
77impl StateUpdate {
78    pub fn new() -> Self {
79        StateUpdate::default()
80    }
81
82    pub fn merge_updates(updates: Vec<StateUpdate>) -> StateUpdate {
83        let mut merged = StateUpdate::default();
84        for update in updates {
85            merged.in_accounts.extend(update.in_accounts);
86            merged.out_accounts.extend(update.out_accounts);
87            merged
88                .account_transactions
89                .extend(update.account_transactions);
90            merged.transactions.extend(update.transactions);
91            merged
92                .leaf_nullifications
93                .extend(update.leaf_nullifications);
94
95            for (key, value) in update.indexed_merkle_tree_updates {
96                // Insert only if the seq is higher.
97                if let Some(existing) = merged.indexed_merkle_tree_updates.get_mut(&key) {
98                    if value.seq > existing.seq {
99                        *existing = value;
100                    }
101                } else {
102                    merged.indexed_merkle_tree_updates.insert(key, value);
103                }
104            }
105        }
106        merged
107    }
108}