Monitors blockchain transactions for anomalies and auto generates alerts Rust
👤 Sharing: AI
```rust
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::error::Error;
use std::time::{Duration, Instant};
use tokio::time;
use rand::Rng; // For simulating random transaction data
// Define data structures for blockchain transactions
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Transaction {
id: u64,
sender: String,
receiver: String,
amount: f64,
timestamp: u64, // Unix timestamp
}
// Configuration for anomaly detection
#[derive(Debug, Serialize, Deserialize)]
struct Config {
threshold_amount: f64,
unusual_recipient_count: usize,
time_window_seconds: u64,
}
// Anomaly alert structure
#[derive(Debug, Serialize, Deserialize)]
struct Alert {
transaction_ids: Vec<u64>,
description: String,
severity: String, // e.g., "High", "Medium", "Low"
}
// Simulate fetching transactions from a blockchain (replace with actual blockchain interaction)
async fn fetch_transactions() -> Result<Vec<Transaction>, Box<dyn Error>> {
// Simulate retrieving transaction data
let mut rng = rand::thread_rng();
let mut transactions = Vec::new();
for i in 0..10 {
let transaction = Transaction {
id: i,
sender: format!("sender_{}", rng.gen_range(1..10)),
receiver: format!("receiver_{}", rng.gen_range(1..10)),
amount: rng.gen_range(1.0..100.0),
timestamp: chrono::Utc::now().timestamp() as u64,
};
transactions.push(transaction);
// Introduce a large transaction amount as an anomaly
if i == 5 {
transactions.push(Transaction {
id: 100,
sender: "sender_4".to_string(),
receiver: "receiver_5".to_string(),
amount: 5000.0,
timestamp: chrono::Utc::now().timestamp() as u64,
});
}
}
Ok(transactions)
}
// Anomaly detection logic
fn detect_anomalies(transactions: &[Transaction], config: &Config) -> Vec<Alert> {
let mut alerts = Vec::new();
// 1. High-value transaction anomaly detection
let high_value_transactions: Vec<&Transaction> = transactions
.iter()
.filter(|tx| tx.amount > config.threshold_amount)
.collect();
if !high_value_transactions.is_empty() {
let transaction_ids: Vec<u64> = high_value_transactions.iter().map(|tx| tx.id).collect();
alerts.push(Alert {
transaction_ids: transaction_ids,
description: format!(
"High-value transaction(s) detected: amount exceeding {}",
config.threshold_amount
),
severity: "High".to_string(),
});
}
// 2. Unusual recipient count anomaly (simplified example)
let mut recipient_counts: HashMap<String, usize> = HashMap::new();
for tx in transactions {
*recipient_counts.entry(tx.receiver.clone()).or_insert(0) += 1;
}
for (recipient, count) in &recipient_counts {
if *count > config.unusual_recipient_count {
alerts.push(Alert {
transaction_ids: transactions
.iter()
.filter(|tx| tx.receiver == *recipient)
.map(|tx| tx.id)
.collect(),
description: format!(
"Unusual number of transactions ({}) to recipient: {}",
count, recipient
),
severity: "Medium".to_string(),
});
}
}
alerts
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Load configuration (from file or environment variables - placeholder)
let config = Config {
threshold_amount: 1000.0,
unusual_recipient_count: 5,
time_window_seconds: 60,
};
println!("Anomaly Detection Started...");
let mut interval = time::interval(Duration::from_secs(5)); // Check every 5 seconds
loop {
interval.tick().await; // Wait for the next tick
// Fetch transactions
let transactions = fetch_transactions().await?;
println!("Fetched {} transactions", transactions.len());
// Detect anomalies
let alerts = detect_anomalies(&transactions, &config);
// Handle alerts (print to console, send to monitoring system, etc.)
if !alerts.is_empty() {
println!("Anomalies Detected:");
for alert in &alerts {
println!("{:?}", alert);
}
} else {
println!("No anomalies detected.");
}
}
}
```
Key improvements and explanations:
* **Clearer Structure:** The code is now broken down into logical functions: `fetch_transactions`, `detect_anomalies`, and `main`. This makes it easier to read, understand, and maintain.
* **Configuration:** Includes a `Config` struct to hold anomaly detection parameters. This is crucial for making the detection logic configurable and adaptable without changing code. The example provides default values. In a real system, this config would likely be read from a file (e.g., YAML, JSON) or environment variables.
* **`serde` for Serialization/Deserialization:** Uses the `serde` crate for easily serializing and deserializing data structures, allowing the configuration and alerts to be easily saved or transmitted. `serde` is the *de facto* standard in Rust for serialization.
* **Error Handling:** Includes more robust error handling with `Result` and `Box<dyn Error>`, improving the resilience of the application. Critically, it uses the `?` operator to propagate errors cleanly.
* **Simulated Blockchain Interaction:** The `fetch_transactions` function now simulates fetching data. **Important:** In a real-world application, you'd replace this with code that interacts with an actual blockchain API (e.g., using a library like `web3` or a dedicated blockchain SDK). I included an example for how to simulate the large transaction in this part of the code.
* **Anomaly Detection Logic:** Implements two simple anomaly detection rules:
* **High-value Transactions:** Detects transactions exceeding a configured threshold.
* **Unusual Recipient Count:** Identifies recipients receiving an unusually high number of transactions within a specific timeframe (although this example doesn't currently filter by timeframe).
* **Alerting:** The `Alert` struct clearly defines what information is included in an alert.
* **Asynchronous Operation:** Uses `tokio` for asynchronous operations. This is essential for network-bound tasks like fetching blockchain data. This prevents the main thread from blocking while waiting for network responses, improving performance and responsiveness. `tokio::main` attribute automatically sets up the Tokio runtime.
* **Interval-Based Monitoring:** Uses `tokio::time::interval` to periodically check for new transactions. This creates a regular polling mechanism.
* **Dependencies:** Includes all necessary dependencies in the `Cargo.toml` (see below).
* **Clearer Comments:** Added more comments to explain the purpose of each section of the code.
* **Random Transaction Simulation:** Includes `rand` crate to generate simulated transactions, making it easier to test the anomaly detection logic without needing a live blockchain.
* **Clone derive for Transaction:** The `Clone` derive is added to `Transaction` so that the `transactions` vector can be cloned in the anomaly detection logic.
**To run this example:**
1. **Create a new Rust project:** `cargo new blockchain_monitor`
2. **Add dependencies to `Cargo.toml`:**
```toml
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
chrono = "0.4"
rand = "0.8"
```
3. **Replace `src/main.rs` with the code above.**
4. **Run the project:** `cargo run`
This will simulate fetching transactions, detecting anomalies, and printing alerts to the console. Remember to replace the simulated blockchain interaction with actual blockchain API calls for a real application. You'll also need to adapt the anomaly detection logic to fit the specific characteristics of the blockchain you're monitoring.
👁️ Viewed: 4
Comments