diff --git a/Cargo.lock b/Cargo.lock index 02bc59b4..a862d91f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,6 +135,7 @@ dependencies = [ "chrono", "hex-literal", "ring", + "serde", "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index df338653..d48d5c7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ 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"]} chrono = "0.4.37" hex-literal = "0.4.1" ring = "0.17.8" diff --git a/src/lib.rs b/src/lib.rs index f2d5b10c..5b055103 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,10 @@ #![allow(dead_code, unused)] mod transactions; -use std::{fs::{self, File}, io}; +// use core::panicking::panic; +use std::io::{self, Read}; +use std::fs::{self, File}; +use std::path::Path; use serde_json; use transactions::tx::{Tx, TxInput, TxOutput}; @@ -17,11 +20,11 @@ pub fn read_mempool(path: &str){ // let file_size = fs::metadata(&file_path).expect("Falha ao ler o arquivo"); // file.sync_all(); // println!("Size: {} File: {}", file); - let transaction_json: serde_json::Value = read_tx_from_file(&file_path); + let transaction_json: Tx = read_tx_from_file(&file_path); - let tx: Tx = convert_json_tx_to_struct(transaction_json); + // let tx: Tx = convert_json_tx_to_struct(transaction_json); - println!("{:?}", tx); + println!("{:?}", transaction_json.vin[0].txid); // if transaction["vin"][0]["txid"] == "491cd7b98e0eec28eb9a97e061fcd71854ac103bdbc4d8a83b6613394d29489e" { // println!("{:?}", transaction); // } @@ -31,32 +34,38 @@ pub fn read_mempool(path: &str){ // is_coinbase(tx_in_json); } -pub fn read_tx_from_file(file_path: &str) -> serde_json::Value { - let contents = fs::read_to_string(file_path) - .expect("Error while reading file"); +pub fn read_tx_from_file(file_path: &str) -> Tx { + let mut file_content: String = String::new(); + let path = Path::new(file_path); + let mut file = File::open(path).expect("Error while loading file"); + file.read_to_string(&mut file_content).expect("File can not be read"); + + // let contents = fs::read_to_string(file_path) + // .expect("Error while reading file"); - let tx_in_json: serde_json::Value = serde_json::from_str(contents.as_str()) - .expect("Error parsing file content to JSON"); + let tx_in_json: Tx = serde_json::from_str(&file_content).unwrap(); + // .expect("Error parsing file content to JSON"); return tx_in_json; } -pub fn convert_json_tx_to_struct(tx_json: serde_json::Value) -> Tx { - let tx_vin = &tx_json["vin"][0]; - let tx_vout = &tx_json["vout"][0]; - - let mut tx_input_vec: Vec = vec![]; - let mut tx_output_vec: Vec = vec![]; +// TODO: this function is with a problem that all the strings are coming with "\".......\"" +// pub fn convert_json_tx_to_struct(tx_json: serde_json::Value) -> Tx { +// let tx_vin = &tx_json["vin"][0]; +// let tx_vout = &tx_json["vout"][0]; + +// let mut tx_input_vec: Vec = vec![]; +// let mut tx_output_vec: Vec = vec![]; - let tx_input: TxInput = TxInput::new(tx_vin["txid"].to_string(), tx_vin["prevout"]["value"].as_u64().expect("Error while casting tx_in value to u64"), tx_vin["scriptsig"].to_string(), tx_vin["is_coinbase"].as_bool().expect("Error while casting tx_in is_coinbase")); +// let tx_input: TxInput = TxInput::new(tx_vin["txid"].to_string(), tx_vin["prevout"]["value"].as_u64().expect("Error while casting tx_in value to u64"), tx_vin["scriptsig"].to_string(), tx_vin["is_coinbase"].as_bool().expect("Error while casting tx_in is_coinbase")); - let tx_output: TxOutput = TxOutput::new(tx_vout["value"].as_u64().expect("Error while casting tx_out value to u64"), tx_vout["scriptpubkey"].to_string()); +// let tx_output: TxOutput = TxOutput::new(tx_vout["value"].as_u64().expect("Error while casting tx_out value to u64"), tx_vout["scriptpubkey"].to_string()); - tx_input_vec.push(tx_input); - tx_output_vec.push(tx_output); +// tx_input_vec.push(tx_input); +// tx_output_vec.push(tx_output); - Tx::new(tx_json["version"].as_u64().expect("Error while parsing tx version to u64") as u32, tx_input_vec, tx_output_vec) -} +// Tx::new(tx_json["version"].as_u64().expect("Error while parsing tx version to u64") as u32, tx_input_vec, tx_output_vec) +// } pub fn is_coinbase(tx: serde_json::Value) -> bool { let tx_input = &tx["vin"]; diff --git a/src/transactions/mod.rs b/src/transactions/mod.rs index d81ca775..d7c32947 100644 --- a/src/transactions/mod.rs +++ b/src/transactions/mod.rs @@ -1 +1 @@ -pub mod tx; \ No newline at end of file +pub mod tx; diff --git a/src/transactions/tx.rs b/src/transactions/tx.rs index f44cb2e7..66574a64 100644 --- a/src/transactions/tx.rs +++ b/src/transactions/tx.rs @@ -1,76 +1,108 @@ #![allow(dead_code, unused)] - +// use serde::{Serialize, Deserialize} // use serde_json; // use ring::digest; -#[derive(Debug)] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] pub struct Tx{ pub version: u32, - pub tx_input: Vec, - pub tx_size: u64, - pub tx_output: Vec + pub locktime: u32, + pub vin: Vec, + pub vout: Vec, + // tx_size: u64, } + impl Tx{ - pub fn new (version: u32, tx_input: Vec, tx_output: Vec) -> Self { + pub fn new (version: u32, locktime: u32, vin: Vec, vout: Vec) -> Self { let mut tx_size = 32 + 64; - tx_output.iter().for_each(|output| tx_size += output.get_tx_output_size_in_bytes()); - tx_input.iter().for_each(|input| tx_size += input.get_tx_input_size_in_bytes()); + vout.iter().for_each(|output| tx_size += output.get_tx_output_size_in_bytes()); + vin.iter().for_each(|input| tx_size += input.get_tx_input_size_in_bytes()); Self { version, - tx_input, - tx_size, - tx_output, + locktime, + vin, + vout, + // tx_size, } } + + // pub fn get_tx_size(&self) -> u64 { + // self.tx_size + // } } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct TxInput{ - tx_id: String, - value: u64, - signature_script: String, - is_coinbase: bool, + pub txid: String, + pub vout: u32, + pub prevout: TxPrevOut, + pub scriptsig: String, + pub scriptsig_asm: String, + pub witness: Vec, + pub is_coinbase: bool, + pub sequence: u64, } impl TxInput{ - pub fn new(tx_id: String, value: u64, signature_script: String, is_coinbase: bool) -> Self{ + pub fn new(txid: String,vout: u32,prevout: TxPrevOut,scriptsig: String,scriptsig_asm: String,witness: Vec,is_coinbase: bool,sequence: u64,) -> Self{ Self{ - tx_id, - value, - signature_script, - is_coinbase + txid, + vout, + prevout, + scriptsig, + scriptsig_asm, + witness, + is_coinbase, + sequence, } } fn get_tx_input_size_in_bytes(&self) -> u64{ - let sigscript_size: u64 = self.signature_script.len() as u64 * 32; - let tx_id_size: u64 = self.tx_id.len() as u64 * 32; - return 64 + sigscript_size + tx_id_size + 1; + let sigscript_size: u64 = self.scriptsig.len() as u64 * 32; + let txid_size: u64 = self.txid.len() as u64 * 32; + return 64 + sigscript_size + txid_size + 1; } } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] +pub struct TxPrevOut{ + pub scriptpubkey: String, + pub scriptpubkey_asm: String, + pub scriptpubkey_type: String, + pub scriptpubkey_address: String, + pub value: u64, +} + +#[derive(Debug, Serialize, Deserialize)] pub struct TxOutput { + pub scriptpubkey: String, + pub scriptpubkey_asm: String, + pub scriptpubkey_type: String, + pub scriptpubkey_address: String, pub value: u64, - pub pk_script: String, } impl TxOutput{ - pub fn new(value:u64, pk_script: String) -> Self { + pub fn new(scriptpubkey: String, scriptpubkey_asm: String, scriptpubkey_type: String, scriptpubkey_address: String, value: u64,) -> Self { Self{ - value, - pk_script + scriptpubkey, + scriptpubkey_asm, + scriptpubkey_type, + scriptpubkey_address, + value } } pub fn get_tx_output_size_in_bytes(&self) -> u64{ - let pk_script_size: u64 = self.pk_script.len() as u64 * 32; + let pk_script_size: u64 = self.scriptpubkey.len() as u64 * 32; return pk_script_size + 64 } -} \ No newline at end of file +}