Skip to content

Commit 8812f95

Browse files
refactor: improve transaction parsing logic and clean up code
1 parent 5c20ac7 commit 8812f95

File tree

5 files changed

+67
-31
lines changed

5 files changed

+67
-31
lines changed

src/ingester/parser/mod.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,55 @@ pub fn parse_transaction(tx: &TransactionInfo, slot: u64) -> Result<StateUpdate,
6363
is_compression_transaction = true;
6464
state_updates.push(state_update);
6565
} else {
66-
for (index, _) in ordered_instructions.iter().enumerate() {
67-
if ordered_instructions.len() - index > 2 {
68-
if let Some(state_update) = parse_public_transaction_event_v1(
69-
tx,
70-
slot,
71-
&ordered_instructions[index],
72-
&ordered_instructions[index + 1],
73-
&ordered_instructions[index + 2],
74-
)? {
75-
is_compression_transaction = true;
76-
state_updates.push(state_update);
66+
for (index, instruction) in ordered_instructions.iter().enumerate() {
67+
if ordered_instructions.len() - index > 1 {
68+
if get_compression_program_id() == instruction.program_id {
69+
// Look for a NOOP_PROGRAM_ID instruction after one or two SYSTEM_PROGRAM instructions
70+
// We handle up to two system program instructions in the case where we also have to pay a tree rollover fee
71+
let mut noop_instruction_index = None;
72+
let mut system_program_count = 0;
73+
let mut all_intermediate_are_system = true;
74+
75+
// Search for the NOOP instruction, ensuring we find at least one SYSTEM_PROGRAM but no more than two
76+
for i in (index + 1)..ordered_instructions.len() {
77+
let current_instruction = &ordered_instructions[i];
78+
79+
if current_instruction.program_id == NOOP_PROGRAM_ID {
80+
noop_instruction_index = Some(i);
81+
break;
82+
} else if current_instruction.program_id == SYSTEM_PROGRAM {
83+
system_program_count += 1;
84+
if system_program_count > 2 {
85+
all_intermediate_are_system = false;
86+
break;
87+
}
88+
} else {
89+
all_intermediate_are_system = false;
90+
break;
91+
}
92+
}
93+
94+
// If we found a NOOP instruction, exactly one or two SYSTEM_PROGRAM instructions, and all intermediates were valid
95+
if let Some(noop_index) = noop_instruction_index {
96+
if system_program_count >= 1
97+
&& system_program_count <= 2
98+
&& all_intermediate_are_system
99+
{
100+
if let Some(state_update) = parse_public_transaction_event_v1(
101+
tx,
102+
slot,
103+
instruction,
104+
&ordered_instructions[noop_index],
105+
)? {
106+
is_compression_transaction = true;
107+
state_updates.push(state_update);
108+
}
109+
}
110+
}
77111
}
78-
} else if ordered_instructions.len() - index > 1 {
112+
}
113+
114+
if ordered_instructions.len() - index > 1 {
79115
if let Some(state_update) = parse_merkle_tree_event(
80116
&ordered_instructions[index],
81117
&ordered_instructions[index + 1],

src/ingester/parser/tx_event_parser.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::ingester::error::IngesterError;
33
use crate::ingester::parser::indexer_events::PublicTransactionEvent;
44
use crate::ingester::parser::state_update::{AccountTransaction, StateUpdate};
55
use crate::ingester::parser::tree_info::TreeInfo;
6-
use crate::ingester::parser::{get_compression_program_id, NOOP_PROGRAM_ID, SYSTEM_PROGRAM};
6+
use crate::ingester::parser::{get_compression_program_id, NOOP_PROGRAM_ID};
77
use crate::ingester::typedefs::block_info::{Instruction, TransactionInfo};
88
use anchor_lang::AnchorDeserialize;
99
use light_compressed_account::TreeType;
@@ -14,28 +14,27 @@ use std::collections::HashMap;
1414
pub fn parse_public_transaction_event_v1(
1515
tx: &TransactionInfo,
1616
slot: u64,
17-
instruction: &Instruction,
18-
next_instruction: &Instruction,
19-
next_next_instruction: &Instruction,
17+
compression_instruction: &Instruction,
18+
noop_instruction: &Instruction,
2019
) -> Result<Option<StateUpdate>, IngesterError> {
21-
if get_compression_program_id() == instruction.program_id
22-
&& next_instruction.program_id == SYSTEM_PROGRAM
23-
&& next_next_instruction.program_id == NOOP_PROGRAM_ID
20+
if get_compression_program_id() == compression_instruction.program_id
21+
&& noop_instruction.program_id == NOOP_PROGRAM_ID
2422
&& tx.error.is_none()
2523
{
2624
info!(
2725
"Indexing transaction with slot {} and id {}",
2826
slot, tx.signature
2927
);
3028

31-
let public_transaction_event =
32-
PublicTransactionEvent::deserialize(&mut next_next_instruction.data.as_slice())
33-
.map_err(|e| {
34-
IngesterError::ParserError(format!(
35-
"Failed to deserialize PublicTransactionEvent: {}",
36-
e
37-
))
38-
})?;
29+
let public_transaction_event = PublicTransactionEvent::deserialize(
30+
&mut noop_instruction.data.as_slice(),
31+
)
32+
.map_err(|e| {
33+
IngesterError::ParserError(format!(
34+
"Failed to deserialize PublicTransactionEvent: {}",
35+
e
36+
))
37+
})?;
3938
create_state_update_v1(tx.signature, slot, public_transaction_event.into()).map(Some)
4039
} else {
4140
Ok(None)

src/migration/migrations/standard/m20220101_000001_init.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ impl MigrationTrait for Migration {
2929
if manager.get_database_backend() == DatabaseBackend::Postgres {
3030
// Max balance of an individual account or token account is 2**64. bigint2 is 5000x larger than that to account for batch updates where update the database with new account balances
3131
// before closing spent accounts and extreme cases where a single wallet owns an excessive amount of account / tokens with high number of lamports.
32-
//
33-
// We go a bit overboard here, but it's ok because bigint2 is not the storage bottleneck.
32+
//
33+
// We go a bit overboard here, but it's ok because bigint2 is not the storage bottleneck.
3434
execute_sql(
3535
manager,
3636
"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"slot":380876342,"transaction":["AVBckWHufnpo5k31sra8b25PSBJ8wZHFHxTVzywKv0Md7zI6gWtYfZvsCWGTf1RRnAjpOZuyiwMGAXVQyZKKvgYBAAgOwZ1VN79Su7sp1VDkyLqdpMjhOkGz6rq65faB3x1IZfcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuzCqyCzEXXw00QukxWWF121rpHf8sXrOfkw90a+RQ1DQHJKKtF02VZWjTodxf7sACKGdIvBSydofmIxHxX3joNAclJOOYCWqhG9HrdwjHLVUzp6/nSXH2t5N+WwRp7vg0BydoNu62NBXntAkJwqhoi8SO5svaEsnL1rvZDx6HSHuvEjPsyZLvDS/XFpag0/GdQAG8phtlvI1vIh1703UQJLDbsIvUXgwD9tEqqav/P8KRuHLxkHA4+0J2hO571CAMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAACRWjVyN5To+2XQdba3JpnDjdAuWUi3Ww5aBBjoCXW0TmyRiwvXzPkVREinq/ao85eCmh6P0Ip/DQs6q4eFL8MvuzKHUQXK6FtbREdgftv+FFJ7+0I5EcpAQjv9FSeiZ1C7wPwLtHyi90xBEulKsTz6PGNOXcF+rLA80aI81+eHwGp1X4ITkFTUQksVrwxDDPL0t/mHk62hJS1I82ZsbLziCaTFY1ZnIqrdkzA9GHuiwY069xIwQGrFOy4rAIF320AwgACQPI0AIAAAAAAAgABQK9MwYACREAAAoNBgwLBwkJCQkBBQIDBKQCozTI54wDRboYAQAAARmUiawkWKBeQgS9VpBohrNw/E/2OQpKx6pzowyS3rilGMyVSZ4X/7Vdcv5gdSVa4h/WuMi29PJZdF35DzCniggZckae63vUjghxUk09yCHBH9fwLWOsv3mCeXV4H+B7+ybQjx0RHTjqWYbG71iAZI45k77VJGJNaGl3g3ctnL2TkGZ00DAQ8bqxNZpC7wnKZj9A8c6E0wN52xW0emTnFsIAAQAAAACABldIcAAAAAABu3EBAADOAQAAAgAAAMGdVTe/Uru7KdVQ5Mi6naTI4TpBs+q6uuX2gd8dSGX3ALBOK95vAAAAAgDar8QcMl6GrjKzzx6mdme7F5jKQJxdMWqbMaIVnD+mAwDQtytqAAAAAAMAAAAAAA==","base64"],"meta":{"err":null,"status":{"Ok":null},"fee":80001,"preBalances":[2783445420,1,9647410200,10977200160,9525266460,9524739960,1392000,1141440,1,1141440,12348739,0,1141440,1141440],"postBalances":[2783359819,1,9647415200,10977200460,9525266760,9524739960,1392000,1141440,1,1141440,12348739,0,1141440,1141440],"innerInstructions":[{"index":2,"instructions":[{"programIdIndex":13,"accounts":[0,10,6,12,11,7,9,13,13,1,13,5,2,3,4],"data":"22TjKTEEcMHaSkGa3aqCjXZtU5FUj2njS6prCwFsjUx5oJKmMAjL1uVSAz8YmfqVZgxVQ92LhKQqeDKCuktXwfRpKZxGC6WqdYegv6Zo5fTWoE4QBMLst4prpuWeTQyuN4YUpqVrcDJc4T2WhSVNWeg5A3xpDrYd9VBYFGzkq8zfpZx9vQwwbEffgu5Mjubn5DZPkCJcZUTjgKYKC48xUugXTbQFdHGM1ExKdvgKdVD5vU2BQAgKUAUB8aUnpVQqgdq3jH4a5gQwAggw88MQm28Hqkw4oL7TTgrWkJC4teUvxAQkQ7NgD67bZtRRxGwVw93yHDzQt885zk3AqKaTL7kL5zwpQ1u9dTrUsgwkj8iJ3rW8aor1i3wgJpZYzGP1RiWdNR4L6s3Y9niGFrrQB4kLTdWHyQhUueYECFpufryV3RnTmmf5hY1x8F3zUjFquzgviWKX7y1RaBwmVXQ1qsdt9iMgNuSGrMCVpz92h27FK2Ugyu8rkUxJXDsYy9dgdSjnJbBhuQ3K8bX1f6qEmdiF4VsuoqTFQnra5R7VsMrHbW5Zu3gdX47gyvfbAjd3Rxdt9djw1YWPKYzzNeNwAypjVTePEqiQDrTPv4E7hjvrPQJG2QTNq6yds4h84q9acfpdZnLyZCWjDuynkBwjskymfxF72k8kjVrQfSc8WBtQ23pnW3sMwbeHbNXkzgJrao9jxiGdfry46QYsSLvDHDyuWvwo7cE4MbuKZZXhfD1fvWbNpxTHyC47BHADS4Tgsj6627FLixjRpBZ2a8utTvu14es8UZzspVtQraS47HGqXJPt7sZFKUFKw7GYNEiXpd7p34uLTeBNbBps6EgHfkPK1PYM4j2Trkkf7zVBMhjBJQffBMYMqWzDc7h","stackHeight":2},{"programIdIndex":7,"accounts":[0,11,6,1,2,5],"data":"WiZw2hSp2LSxinAV63skVmsJMhyg37nsMpMABKHpxqFPSz6PMHM9F2HemKq8","stackHeight":3},{"programIdIndex":1,"accounts":[0,2],"data":"3Bxs4PckVVt51W8w","stackHeight":3},{"programIdIndex":7,"accounts":[0,11,6,1,3,4],"data":"7UWNMdwFJEWBQPSoUMHBWZGDsTr9ra7LJEZ2ZmTTLqULxjy4U4sejJbU6HpLW7VUk3zMJTHCdKNJHGAHeUMw3hWKcdZiS2E9RD2Q7fLhR9P","stackHeight":3},{"programIdIndex":1,"accounts":[0,3],"data":"3Bxs48DZ3Zx6m4mD","stackHeight":4},{"programIdIndex":1,"accounts":[0,4],"data":"3Bxs48DZ3Zx6m4mD","stackHeight":4},{"programIdIndex":12,"accounts":[],"data":"6mLqCakjkxPs3hb7JKiVxBWv438hyQ6ziFhCSn8ahdACfu886HBNpMe4vpxbxubEWoYhboFCWqTtDknnRN6fr6akR2noRXYkEAURf9X51AHgiKQJog8uiGtccse18mZR7qk7cR1T5FZXZZsJUjoFLM2HXL2Q9nrGTNPvVTYKTk7pABQNcGmomLxfZzLPTXxzooJ26N3bBBfxv3zfJoTneP3Zd8o1PYKza6Vg3cva93rfByrKqzZw73jYQb36wtM3zdDhCV1uKkpYjVen1wKuqGMwikjgkhDDSRqXCT9hvZVZC4ahTpwPJW7y4MGCD6VFcVPkXAkvCnQohZZnqeZ5p9FUiqqP9BuFg9ofyTYbzjL5kuUaXk2B1dBHJD5AUumTRZfScw8TPhatXwgpdfY17JGJ5T4g7JW3yFcea9DJZR5HwnTQ8yUph1WKaXupzsXmAPdvsw1vnuPVa1qASuDyvEEAu6g3bvh39ut6CNCoCrPAtbh8h2efpiEMftSfgFVfEwnviAdMAjhCNEJrRzohVpCtz2LYyS5CVgPCN4z5xUJ5du8shU8Aa8JPgr7uuRvASi9KWfHqJLDfvSuxyZCtTzGRxgxu6jzFsUe1Q4gqhd3Fbm1mh88DMq9TgVn1oAnKLbvEgtJeFCLomsUvx5FhGY3FE3PDfehFZqMoZDEif81dasUXCxNycXswBL2tfFsQHpwhYV7hgJVfkwcf5mWBfK4bpMtUNUQAgU9iqVMNJXem3jSaexKQLUyvSgG5MXvgKUV4nWFBKbqoQthQMduXb4mV2qqX4iBWpctZAYaoC6FLhguMhu9Xz7PARixSB3AFiuBq3cYDc2G6anXRk6TPcVm1pYkthiuBguMeiZRn26e3ufBmWGykaizR6dW2e4NPYHyAeFpZq9","stackHeight":3}]}],"logMessages":["Program ComputeBudget111111111111111111111111111111 invoke [1]","Program ComputeBudget111111111111111111111111111111 success","Program ComputeBudget111111111111111111111111111111 invoke [1]","Program ComputeBudget111111111111111111111111111111 success","Program cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m invoke [1]","Program log: Instruction: Transfer","Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 invoke [2]","Program log: Instruction: InvokeCpi","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq invoke [3]","Program log: Instruction: InsertIntoNullifierQueues","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq consumed 10550 of 210228 compute units","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq success","Program 11111111111111111111111111111111 invoke [3]","Program 11111111111111111111111111111111 success","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq invoke [3]","Program log: Instruction: AppendLeavesToMerkleTrees","Program 11111111111111111111111111111111 invoke [4]","Program 11111111111111111111111111111111 success","Program 11111111111111111111111111111111 invoke [4]","Program 11111111111111111111111111111111 success","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq consumed 80781 of 167762 compute units","Program compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq success","Program noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV invoke [3]","Program noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV consumed 97 of 83046 compute units","Program noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV success","Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 consumed 269947 of 352217 compute units","Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 success","Program cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m consumed 325019 of 406161 compute units","Program cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m success"],"preTokenBalances":[],"postTokenBalances":[],"rewards":[],"loadedAddresses":{"writable":[],"readonly":[]},"computeUnitsConsumed":325319},"version":"legacy","blockTime":1747252042}

tests/integration_tests/e2e_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,6 @@ async fn test_nullfiier_and_address_queue_transactions(
691691
}
692692
}
693693

694-
695694
#[named]
696695
#[rstest]
697696
#[tokio::test]
@@ -710,7 +709,8 @@ async fn test_transaction_with_tree_rollover_fee(
710709
},
711710
)
712711
.await;
713-
let txn = "2cBtegqLxQztcngNF4qWGZYEuGiwFvmSpak4dqNaGHHQRDBGuYg24ZSG54BpRaWS5Cr4v6AWLV42FWvEjQk2ESWy";
712+
let txn =
713+
"2cBtegqLxQztcngNF4qWGZYEuGiwFvmSpak4dqNaGHHQRDBGuYg24ZSG54BpRaWS5Cr4v6AWLV42FWvEjQk2ESWy";
714714
let txn = cached_fetch_transaction(&name, setup.client.clone(), txn).await;
715715
let status_update = parse_transaction(&txn.try_into().unwrap(), 0).unwrap();
716716
// Assert that status update has at least one account

0 commit comments

Comments
 (0)