Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
justcode740 committed Apr 8, 2024
1 parent e72da97 commit 6aafcc5
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
btc_mine_simulator/target/
1 change: 1 addition & 0 deletions btc_mine_simulator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
89 changes: 89 additions & 0 deletions btc_mine_simulator/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions btc_mine_simulator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "btc_mine_simulator"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
73 changes: 73 additions & 0 deletions btc_mine_simulator/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::fs;
use std::io;
use std::path::Path;

mod tx;
mod validate;
use tx::Transaction;
use validate::validate_transaction;

fn read_transactions_from_dir(dir: &Path) -> io::Result<(Vec<Transaction>, usize, usize)> {
let mut transactions = Vec::new();
let mut total_files = 0;
let mut failed_parses = 0;

for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
total_files += 1;
match fs::read_to_string(&path) {
Ok(data) => {
match serde_json::from_str::<Transaction>(&data) {
Ok(transaction) => transactions.push(transaction),
Err(e) => { // Capture the parse error
failed_parses += 1;
println!("Failed to parse file: {:?}, Reason: {}", path.display(), e);
// Prints out the specific reason for the parse failure
},
}
},
Err(e) => { // Capture the file read error
println!("Failed to read file: {:?}, Reason: {}", path.display(), e);
// This case handles file read errors
}
}
}
}
for tx in &transactions {
// println!("{:?}", tx.locktime);
if tx.locktime != 0 {
println!("wow {:?}", tx.locktime);
}
}

println!("Total files processed: {}", total_files);
println!("Failed to parse: {}", failed_parses);
Ok((transactions, total_files, failed_parses))
}

fn main() {
let dir = Path::new("../mempool");
let txs = match read_transactions_from_dir(dir) {
Ok((transactions, total_files, failed_parses)) => {
println!("Successfully parsed transactions: {}", transactions.len());
println!("Total files: {}", total_files);
println!("Failed parses: {}", failed_parses);
transactions
},
Err(e) => panic!("Error reading transactions: {}", e),
};
let mut res = 0;
for tx in &txs {
if let Err(e) = validate_transaction(tx) {
println!("{:?}", tx.);
res += 1;
println!("error: {:?}", e);

}

}
println!("{:?}", res);

}
40 changes: 40 additions & 0 deletions btc_mine_simulator/src/tx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Transaction {
pub version: i32,
pub locktime: u32,
pub vin: Vec<Input>,
pub vout: Vec<Output>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Input {
pub txid: String,
pub vout: u32,
pub prevout: PrevOut,
pub scriptsig: String,
pub scriptsig_asm: String,
pub witness: Option<Vec<String>>,
pub is_coinbase: bool,
pub sequence: u32,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PrevOut {
pub scriptpubkey: String,
pub scriptpubkey_asm: String,
pub scriptpubkey_type: String,
pub scriptpubkey_address: String,
pub value: u64,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Output {
pub scriptpubkey: String,
pub scriptpubkey_asm: String,
pub scriptpubkey_type: String,
pub scriptpubkey_address: Option<String>,
pub value: u64,
}

44 changes: 44 additions & 0 deletions btc_mine_simulator/src/validate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use serde::{Deserialize, Serialize};

use crate::tx::Transaction;

// Assuming the structs Transaction, Input, Output, PrevOut are defined as above

pub fn validate_transaction(tx: &Transaction) -> Result<(), String> {
if tx.version < 1 || tx.version > 2 {
return Err("Unsupported transaction version".to_string());
}

if tx.vin.is_empty() {
return Err("Transaction has no inputs".to_string());
}

if tx.vout.is_empty() {
return Err("Transaction has no outputs".to_string());
}

for input in &tx.vin {
if input.is_coinbase && tx.vin.len() > 1 {
return Err("Coinbase transaction has more than one input".to_string());
}

if !input.is_coinbase && input.txid.is_empty() {
return Err("Input txid is empty".to_string());
}

if let Some(witness) = &input.witness {
if witness.is_empty() {
return Err("Witness is present but empty".to_string());
}
}
}

// let total_output_value: u64 = tx.vout.iter().map(|output| output.value).sum();
// if total_output_value == 0 {
// return Err("Total output value is 0".to_string());
// }

// Further checks can include scriptsig and scriptpubkey validation, which are complex and require executing the scripts

Ok(())
}
6 changes: 6 additions & 0 deletions btc_mine_simulator/todo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
1. clean up invalid tx
2. compute size and fee for each tx
3. build dep graph, tx1 <- tx2 if tx2 can only be valid after tx1 executed
4. try out some algo, simple one would be greedy with pq, consistently choose the max fee tx that can be selected, but this would def miss some some large fee tx with long dep of tx before it
5. build block with selected tx, find the hash
6. export result to file
Empty file modified run.sh
100644 → 100755
Empty file.
Empty file modified test.sh
100644 → 100755
Empty file.

0 comments on commit 6aafcc5

Please sign in to comment.