diff --git a/examples/txid_collisions.rs b/examples/txid_collisions.rs new file mode 100644 index 0000000..8694de3 --- /dev/null +++ b/examples/txid_collisions.rs @@ -0,0 +1,49 @@ +extern crate electrs; + +extern crate hex; +extern crate log; + +use electrs::{config::Config, store::DBStore}; + +fn max_collision(store: DBStore, prefix: &[u8]) { + let prefix_len = prefix.len(); + let mut prev: Option> = None; + let mut collision_max = 0; + + for row in store.iter_scan(prefix) { + assert!(row.key.starts_with(prefix)); + if let Some(prev) = prev { + let collision_len = prev + .iter() + .zip(row.key.iter()) + .take_while(|(a, b)| a == b) + .count(); + if collision_len > collision_max { + eprintln!( + "{} bytes collision found:\n{:?}\n{:?}\n", + collision_len - prefix_len, + revhex(&prev[prefix_len..]), + revhex(&row.key[prefix_len..]), + ); + collision_max = collision_len; + } + } + prev = Some(row.key.to_vec()); + } +} + +fn revhex(value: &[u8]) -> String { + hex::encode(&value.iter().cloned().rev().collect::>()) +} + +fn run(config: Config) { + if !config.db_path.exists() { + panic!("DB {:?} must exist when running this tool!", config.db_path); + } + let store = DBStore::open(&config.db_path, /*low_memory=*/ false); + max_collision(store, b"T"); +} + +fn main() { + run(Config::from_args()); +}