Skip to content

Commit c2f9c26

Browse files
committed
test: add database handler to check for new receipts, RAV
1 parent 5d8e55a commit c2f9c26

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

integration-tests/src/database_checker.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,4 +898,195 @@ impl DatabaseChecker {
898898

899899
Ok(())
900900
}
901+
902+
/// Diagnostic function to analyze timestamp buffer issues during RAV generation
903+
/// This simulates the exact logic used in tap_core's Manager::collect_receipts
904+
pub async fn diagnose_timestamp_buffer(
905+
&self,
906+
payer: &str,
907+
identifier: &str, // collection_id for V2, allocation_id for V1
908+
buffer_seconds: u64,
909+
version: TapVersion,
910+
) -> Result<()> {
911+
let normalized_payer = payer.trim_start_matches("0x").to_lowercase();
912+
913+
// Get current timestamp in nanoseconds (simulating tap_core logic)
914+
let current_time_ns = std::time::SystemTime::now()
915+
.duration_since(std::time::UNIX_EPOCH)
916+
.unwrap()
917+
.as_nanos() as u64;
918+
919+
let buffer_ns = buffer_seconds * 1_000_000_000; // Convert to nanoseconds
920+
let max_timestamp_ns = current_time_ns - buffer_ns;
921+
922+
println!("\n=== TIMESTAMP BUFFER ANALYSIS ===");
923+
println!("Current time: {} ns", current_time_ns);
924+
println!("Buffer: {} seconds = {} ns", buffer_seconds, buffer_ns);
925+
println!("Max eligible timestamp: {} ns", max_timestamp_ns);
926+
println!(
927+
"Time difference: {:.2} seconds ago",
928+
buffer_ns as f64 / 1_000_000_000.0
929+
);
930+
931+
// Get last RAV timestamp to determine min_timestamp_ns
932+
let last_rav_timestamp = match version {
933+
TapVersion::V2 => {
934+
sqlx::query_scalar::<_, Option<BigDecimal>>(
935+
r#"
936+
SELECT MAX(timestamp_ns)
937+
FROM tap_horizon_ravs
938+
WHERE collection_id = $1 AND LOWER(payer) = $2
939+
"#,
940+
)
941+
.bind(identifier)
942+
.bind(&normalized_payer)
943+
.fetch_one(&self.pool)
944+
.await?
945+
}
946+
TapVersion::V1 => sqlx::query_scalar::<_, Option<BigDecimal>>(
947+
r#"
948+
SELECT MAX(timestamp_ns)
949+
FROM scalar_tap_ravs
950+
WHERE allocation_id = $1 AND LOWER(sender_address) = $2
951+
"#,
952+
)
953+
.bind(identifier)
954+
.bind(&normalized_payer)
955+
.fetch_optional(&self.pool)
956+
.await?
957+
.flatten(),
958+
};
959+
960+
let min_timestamp_ns = last_rav_timestamp
961+
.clone()
962+
.map(|ts| ts.to_string().parse::<u64>().unwrap_or(0) + 1)
963+
.unwrap_or(0);
964+
965+
println!("Last RAV timestamp: {:?}", last_rav_timestamp);
966+
println!("Min eligible timestamp: {} ns", min_timestamp_ns);
967+
println!(
968+
"Eligible range: {} to {} ns",
969+
min_timestamp_ns, max_timestamp_ns
970+
);
971+
972+
// Analyze receipts in the identifier
973+
let receipt_analysis = match version {
974+
TapVersion::V2 => {
975+
sqlx::query(
976+
r#"
977+
SELECT
978+
id,
979+
timestamp_ns,
980+
value,
981+
CASE
982+
WHEN timestamp_ns >= $1 AND timestamp_ns < $2 THEN 'ELIGIBLE'
983+
WHEN timestamp_ns >= $2 THEN 'TOO_RECENT'
984+
ELSE 'TOO_OLD'
985+
END as status
986+
FROM tap_horizon_receipts
987+
WHERE collection_id = $3 AND LOWER(payer) = $4
988+
ORDER BY timestamp_ns ASC
989+
"#,
990+
)
991+
.bind(min_timestamp_ns as i64)
992+
.bind(max_timestamp_ns as i64)
993+
.bind(identifier)
994+
.bind(&normalized_payer)
995+
.fetch_all(&self.pool)
996+
.await?
997+
}
998+
TapVersion::V1 => {
999+
sqlx::query(
1000+
r#"
1001+
SELECT
1002+
id,
1003+
timestamp_ns,
1004+
value,
1005+
CASE
1006+
WHEN timestamp_ns >= $1 AND timestamp_ns < $2 THEN 'ELIGIBLE'
1007+
WHEN timestamp_ns >= $2 THEN 'TOO_RECENT'
1008+
ELSE 'TOO_OLD'
1009+
END as status
1010+
FROM scalar_tap_receipts
1011+
WHERE allocation_id = $3 AND LOWER(signer_address) = $4
1012+
ORDER BY timestamp_ns ASC
1013+
"#,
1014+
)
1015+
.bind(min_timestamp_ns as i64)
1016+
.bind(max_timestamp_ns as i64)
1017+
.bind(identifier)
1018+
.bind(&normalized_payer)
1019+
.fetch_all(&self.pool)
1020+
.await?
1021+
}
1022+
};
1023+
1024+
let mut eligible_count = 0;
1025+
let mut too_recent_count = 0;
1026+
let mut too_old_count = 0;
1027+
let mut eligible_value = BigDecimal::from_str("0").unwrap();
1028+
let mut too_recent_value = BigDecimal::from_str("0").unwrap();
1029+
1030+
println!("\n📋 RECEIPT ANALYSIS:");
1031+
for row in &receipt_analysis {
1032+
let id: i64 = row.get("id");
1033+
let timestamp_ns: BigDecimal = row.get("timestamp_ns");
1034+
let value: BigDecimal = row.get("value");
1035+
let status: String = row.get("status");
1036+
1037+
let timestamp_u64 = timestamp_ns.to_string().parse::<u64>().unwrap_or(0);
1038+
let age_seconds = (current_time_ns - timestamp_u64) as f64 / 1_000_000_000.0;
1039+
1040+
match status.as_str() {
1041+
"ELIGIBLE" => {
1042+
eligible_count += 1;
1043+
eligible_value += &value;
1044+
}
1045+
"TOO_RECENT" => {
1046+
too_recent_count += 1;
1047+
too_recent_value += &value;
1048+
}
1049+
"TOO_OLD" => {
1050+
too_old_count += 1;
1051+
}
1052+
_ => {}
1053+
}
1054+
1055+
println!(
1056+
" Receipt {}: {} wei, {:.2}s ago [{}]",
1057+
id, value, age_seconds, status
1058+
);
1059+
}
1060+
1061+
println!("\n📊 SUMMARY:");
1062+
println!(
1063+
" ELIGIBLE for RAV: {} receipts, {} wei",
1064+
eligible_count, eligible_value
1065+
);
1066+
println!(
1067+
" TOO RECENT (in buffer): {} receipts, {} wei",
1068+
too_recent_count, too_recent_value
1069+
);
1070+
println!(" TOO OLD (before last RAV): {} receipts", too_old_count);
1071+
1072+
if eligible_count == 0 && too_recent_count > 0 {
1073+
println!("\n⚠️ DIAGNOSIS: All receipts are too recent (within buffer)");
1074+
println!(
1075+
" 💡 SOLUTION: Wait {} more seconds for receipts to exit buffer",
1076+
buffer_seconds
1077+
);
1078+
} else if eligible_count == 0 && too_old_count > 0 {
1079+
println!("\n⚠️ DIAGNOSIS: All receipts are too old (already covered by RAV)");
1080+
println!(" 💡 SOLUTION: Send new receipts after the last RAV timestamp");
1081+
} else if eligible_count > 0 {
1082+
println!(
1083+
"\n✅ DIAGNOSIS: {} receipts are eligible for RAV generation",
1084+
eligible_count
1085+
);
1086+
} else {
1087+
println!("\n❓ DIAGNOSIS: No receipts found for this identifier");
1088+
}
1089+
1090+
Ok(())
1091+
}
9011092
}

0 commit comments

Comments
 (0)