Skip to content

Commit

Permalink
feat: Optimise log parsing logic
Browse files Browse the repository at this point in the history
  • Loading branch information
eloylp committed Feb 7, 2025
1 parent 00ed5e3 commit fb5d493
Showing 1 changed file with 50 additions and 21 deletions.
71 changes: 50 additions & 21 deletions ampd/src/solana/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,16 @@ where
};

// Check in the logs in a backward way the invocation comes from the gateway
if !event_comes_from_gateway(logs, desired_event_idx) {
error!("Event does not come from the gateway");
return Vote::NotFound;
}
// Check that the event index is in the logs
let Some(event_log) = logs.get(desired_event_idx) else {
error!("Event index is out of bounds");
return Vote::NotFound;
let log = match event_comes_from_gateway(logs, desired_event_idx) {
Ok(log) => log,
Err(err) => {
error!("Cannot find the gateway log: {}", err);
return Vote::NotFound;
}
};

// Second ensure we can parse the event
let event = match gateway_event_stack::parse_gateway_logs(event_log) {
let event = match gateway_event_stack::parse_gateway_logs(&log) {
Ok(ev) => ev,
Err(err) => {
error!("Cannot parse the gateway log: {}", err);
Expand All @@ -122,27 +120,58 @@ where
}

// Check backward in the logs if the invocation comes from the gateway program,
// skipping native program invocations
fn event_comes_from_gateway(logs: &[String], desired_event_idx: usize) -> bool {
// skipping native program invocations and returning the data log if the event comes from the gateway.
//
// Example logs input (indexes are just for reference):
//
// 1. Program gtwLjHAsfKAR6GWB4hzTUAA1w4SDdFMKamtGA5ttMEe invoke [1]
// 2. Program log: Instruction: Call Contract",
// 3. Program data: Y2FsbCBjb250cmFjdF9fXw== 6NGe5cm7PkXHz/g8V2VdRg0nU0l7R48x8lll4s0Clz0= xtlu5J3pLn7c4BhqnNSrP1wDZK/pQOJVCYbk6sroJhY= ZXRoZXJldW0= MHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2YzIwNjAzYzdiODc2NjgyYzEyMTczYmRlZjlhMWRjYTUyOGYxNGZk 8J+QqvCfkKrwn5Cq8J+Qqg==",
// 4. Program gtwLjHAsfKAR6GWB4hzTUAA1w4SDdFMKamtGA5ttMEe success"
//
// In the above log example, this function would return the data log at 3, if and only if the event comes from the gateway,
// which is determined by scanning log lines backwards till we find the pattern "Program <gateway_id> invoke" at 1 for the first time.
// It will fail if it finds any other invocation before the gateway invocation, except for the system program. In that case it will omit it and
// continue scanning.
fn event_comes_from_gateway(
logs: &[String],
desired_event_idx: usize,
) -> Result<&str, Box<dyn std::error::Error>> {
let solana_gateway_id = axelar_solana_gateway::id().to_string();
let system_program_id = solana_sdk::system_program::id().to_string();

for log in logs.iter().take(desired_event_idx).rev() {
let parts: Vec<&str> = log.split(' ').collect();
// From the logs, we take only the logs from the desired event index to the first log
let mut logs = logs
.iter()
.take(
desired_event_idx
.checked_add(1)
.expect("To add 1 to index count to get elem take"),
)
.rev(); // +1 because take() gets n elements, not index based.

if parts.len() < 3 && parts.len() > 4 {
continue;
}
if parts[0] == "Program" && parts[2] == "invoke" {
if parts[1] == system_program_id {
// This is the log that, if the event comes from the gateway, will contain the target data log
// It will be returned if the event comes from the gateway.
let data_log = logs.next().ok_or("Cannot find the first log")?;

for log in logs {
let mut parts = log.split(' ');

let program = parts.next().ok_or("Cannot find program log part")?;
let program_id = parts.next().ok_or("Cannot find program_id log part")?;
let action = parts.next().ok_or("Cannot find action log part")?;

if program == "Program" && action == "invoke" {
if program_id == system_program_id {
continue;
}
if parts[1] == solana_gateway_id {
return true;
if program_id == solana_gateway_id {
// We return the data log to be processed by further functions if we confirm the log comes from the gateway
return Ok(data_log);
} else {
break;
}
}
}
false
Err("Log does not belong to the gateway program".into())
}

0 comments on commit fb5d493

Please sign in to comment.