Commit 2b3c4b82 authored by clabby's avatar clabby

Go with geth snapshot method; prune deps for old IPC method

parent 0a208dd6
This diff is collapsed.
......@@ -5,11 +5,7 @@ edition = "2021"
[dependencies]
clap = { version = "4.1.3", features = ["derive"] }
tokio = { version = "1.24.2", features = ["macros"] }
futures = "0.3.25"
rayon = "1.6.1"
eyre = "0.6.8"
ethers = { version = "1.0.2", features = ["ipc"] }
yansi = "0.5.1"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.91"
......
use clap::Parser;
use ethers::providers::{Ipc, Middleware, Provider};
use eyre::Result;
use futures::future;
use rayon::prelude::*;
use serde::Serialize;
use std::sync::Arc;
use yansi::Paint;
#[derive(Parser)]
#[command(version, about)]
struct EofCrawler {
/// The path to the IPC socket to connect to
#[clap(short, long)]
ipc: String,
/// The block to start crawling from
#[clap(short, long)]
start: Option<u64>,
/// The block to end crawling at
#[clap(short, long)]
end: Option<u64>,
}
#[derive(Serialize)]
struct EOFContract {
address: String,
deployment_block: u64,
deployer: String,
bytecode: String,
}
#[tokio::main]
#[allow(dead_code)]
async fn main() -> Result<()> {
// Parse CLI args
let args = EofCrawler::parse();
// Create a new provider with a connection to an IPC socket
let provider = Arc::new(Provider::<Ipc>::connect_ipc(&args.ipc).await?);
// Unless a starting block was specified, begin at genesis.
let start = args.start.unwrap_or(0);
// Get the latest block or use the end specified in the CLI args
let end = match args.end {
Some(block) => block,
None => provider.get_block_number().await?.as_u64(),
};
// Perform a parallel search over blocks [0, block] for contracts
// that were deployed with the EOF prefix.
println!(
"{}",
Paint::green(format!("Starting search on block range [{start}, {end}]"))
);
let tasks: Vec<_> = (start..=end)
.into_iter()
.map(|block_no| {
// Clone the provider's reference counter to move into the task
let provider = Arc::clone(&provider);
// Spawn a task to search for EOF contracts in the block
tokio::spawn(async move {
// Grab the block at the current block number, panic if we were unable
// to fetch it.
let block = provider
.get_block_with_txs(block_no)
.await
.unwrap()
.unwrap();
// Iterate through all transactions within the block in parallel to look
// for creation txs.
block.transactions.into_par_iter().for_each(|tx| {
// `tx.to` is `None` if the transaction is a contract creation
// TODO: Check if contract creation failed.
if tx.to.is_none() {
// TODO: Pull the runtime code from the creation code; store info
// about the contract.
}
});
})
})
.collect();
// Wait on futures in parallel.
future::join_all(tasks).await;
Ok(())
}
......@@ -2,7 +2,7 @@ use clap::Parser;
use eyre::Result;
use serde::{Deserialize, Serialize};
use std::{
fs::File,
fs::{self, File},
io::{BufRead, BufReader},
};
use yansi::{Color, Paint};
......@@ -28,8 +28,6 @@ struct SnapshotAccount {
fn main() -> Result<()> {
let args = EofCrawler::parse();
let mut eof_contracts: Vec<SnapshotAccount> = Vec::new();
let file = File::open(&args.snapshot_file)?;
let mut reader = BufReader::new(file);
......@@ -42,23 +40,26 @@ fn main() -> Result<()> {
.fg(Color::Cyan)
);
let mut eof_contracts: Vec<SnapshotAccount> = Vec::new();
let mut buf = String::new();
// Ignore the first line of the snapshot, which contains the root of the snapshot.
if let Ok(mut num_bytes) = reader.read_line(&mut buf) {
while num_bytes > 0 {
buf.clear();
num_bytes = reader.read_line(&mut buf)?;
if buf.is_empty() {
break;
}
// Check if the account is a contract, and if it is, check if it has an EOF
// prefix.
let contract: SnapshotAccount = serde_json::from_str(&buf)?;
if let Some(code) = contract.code.as_ref() {
if &code[2..4].to_uppercase() == "EF" {
eof_contracts.push(contract);
}
// Ignore the first line of the snapshot, which contains the root.
#[allow(unused_assignments)]
let mut num_bytes = reader.read_line(&mut buf)?;
loop {
buf.clear();
num_bytes = reader.read_line(&mut buf)?;
if num_bytes == 0 {
break;
}
// Check if the account is a contract, and if it is, check if it has an EOF
// prefix.
let contract: SnapshotAccount = serde_json::from_str(&buf)?;
if let Some(code) = contract.code.as_ref() {
if &code[2..4].to_uppercase() == "EF" {
eof_contracts.push(contract);
}
}
}
......@@ -71,7 +72,7 @@ fn main() -> Result<()> {
))
.fg(Color::Cyan)
);
std::fs::write(
fs::write(
"eof_contracts.json",
serde_json::to_string_pretty(&eof_contracts)?,
)?;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment