Skip to content

Commit

Permalink
Parse also blocks with Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouziel committed Jan 6, 2025
1 parent 7475dbe commit 9f13146
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def deserialize_rust(tx_hex, use_txid=False):
"log_file": "",
}
)
return deserializer.parse(tx_hex, 900000, False, use_txid)
return deserializer.parse_transaction(tx_hex, 900000, False, use_txid)


def test_deserialize():
Expand Down
54 changes: 46 additions & 8 deletions counterparty-rs/src/indexer/bitcoin_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,13 @@ fn parse_vout(
}
}

fn create_transaction(tx: &bitcoin::blockdata::transaction::Transaction, config: &Config, height: u32, parse_vouts: bool) -> Transaction {
fn create_transaction(
tx: &bitcoin::blockdata::transaction::Transaction,
config: &Config,
height: u32,
parse_vouts: bool,
use_txid: bool
) -> Transaction {
let tx_bytes = serialize(tx);
let mut vins = Vec::new();
let mut segwit = false;
Expand Down Expand Up @@ -412,7 +418,7 @@ fn create_transaction(tx: &bitcoin::blockdata::transaction::Transaction, config:
let mut data = Vec::new();
let mut potential_dispensers = Vec::new();
let mut err = None;
for (vi, vout) in tx.output.iter().enumerate() {
for vout in tx.output.iter() {
vouts.push(Vout {
value: vout.value.to_sat(),
script_pub_key: vout.script_pubkey.to_bytes(),
Expand Down Expand Up @@ -474,35 +480,43 @@ fn create_transaction(tx: &bitcoin::blockdata::transaction::Transaction, config:
})
};
}
let tx_id = tx.compute_txid().to_string();
let tx_hash;
if segwit && use_txid {
tx_hash = tx_id.clone();
} else {
tx_hash = Sha256dHash::hash(&tx_bytes).to_string();
}
Transaction {
version: tx.version.0,
segwit,
coinbase: tx.is_coinbase(),
lock_time: tx.lock_time.to_consensus_u32(),
tx_id: tx.compute_txid().to_string(),
tx_hash: Sha256dHash::hash(&tx_bytes).to_string(),
tx_id: tx_id,
tx_hash: tx_hash,
vtxinwit,
vin: vins,
vout: vouts,
parsed_vouts,
}
}

pub fn parse_transaction(tx_hex: &str, config: &Config, height: u32, parse_vouts: bool) -> Transaction {

pub fn parse_transaction(tx_hex: &str, config: &Config, height: u32, parse_vouts: bool, use_txid: bool) -> Transaction {
let decoded_tx = hex::decode(tx_hex).expect("Failed to decode hex string");

let transaction: bitcoin::blockdata::transaction::Transaction =
deserialize(&decoded_tx).expect("Failed to deserialize transaction");

return create_transaction(&transaction, config, height, parse_vouts);
return create_transaction(&transaction, config, height, parse_vouts, use_txid);
}


impl ToBlock for Block {
fn to_block(&self, config: Config, height: u32) -> CrateBlock {
let mut transactions = Vec::new();
for tx in self.txdata.iter() {
transactions.push(create_transaction(tx, &config, height, true));
transactions.push(create_transaction(tx, &config, height, true, config.correct_segwit_txids_enabled(height)));
}
CrateBlock {
height,
Expand All @@ -519,6 +533,30 @@ impl ToBlock for Block {
}
}


pub fn parse_block(hex: &str, config: &Config, height: u32, parse_vouts: bool, use_txid: bool) -> Result<CrateBlock, Error> {
let decoded_block = hex::decode(hex).map_err(|e| Error::ParseVout(format!("Failed to decode hex string: {}", e)))?;
let block: Block = deserialize(&decoded_block).map_err(|e| Error::ParseVout(format!("Failed to deserialize block: {}", e)))?;

let mut transactions = Vec::new();
for tx in block.txdata.iter() {
transactions.push(create_transaction(tx, config, height, parse_vouts, use_txid));
}
Ok(CrateBlock {
height,
version: block.header.version.to_consensus(),
hash_prev: block.header.prev_blockhash.to_string(),
hash_merkle_root: block.header.merkle_root.to_string(),
block_time: block.header.time,
bits: block.header.bits.to_consensus(),
nonce: block.header.nonce,
block_hash: block.block_hash().to_string(),
transaction_count: block.txdata.len(),
transactions,
})
}


impl BlockHasPrevBlockHash for Block {
fn get_prev_block_hash(&self) -> &BlockHash {
&self.header.prev_blockhash
Expand Down
2 changes: 1 addition & 1 deletion counterparty-rs/src/indexer/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt::Display;

use pyo3::{exceptions::PyValueError, types::PyDict, FromPyObject, PyAny, PyErr, PyResult};
use tracing::{level_filters::LevelFilter, Level};
use tracing::{level_filters::LevelFilter};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Expand Down
28 changes: 8 additions & 20 deletions counterparty-rs/src/indexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,26 +96,14 @@ impl Deserializer {
Ok(Deserializer { config })
}

pub fn parse(&self, tx_hex: &str, height: u32, parse_vouts: bool, use_txid: bool, py: Python<'_>) -> PyResult<PyObject> {
let tx = self::bitcoin_client::parse_transaction(tx_hex, &self.config, height, parse_vouts);

if tx.segwit && use_txid {
let transaction = self::block::Transaction {
version: tx.version,
segwit: tx.segwit,
coinbase: tx.coinbase,
lock_time: tx.lock_time,
tx_id: tx.tx_id.clone(),
tx_hash: tx.tx_id,
vtxinwit: tx.vtxinwit,
vin: tx.vin,
vout: tx.vout,
parsed_vouts: tx.parsed_vouts,
};
return Ok(transaction.into_py(py))
} else {
return Ok(tx.into_py(py))
}
pub fn parse_transaction(&self, tx_hex: &str, height: u32, parse_vouts: bool, use_txid: bool, py: Python<'_>) -> PyResult<PyObject> {
let tx = self::bitcoin_client::parse_transaction(tx_hex, &self.config, height, parse_vouts, use_txid);
return Ok(tx.into_py(py))
}

pub fn parse_block(&self, block_hex: &str, height: u32, parse_vouts: bool, use_txid: bool, py: Python<'_>) -> PyResult<PyObject> {
let block = self::bitcoin_client::parse_block(block_hex, &self.config, height, parse_vouts, use_txid);
return Ok(block?.into_py(py))
}
}

Expand Down

0 comments on commit 9f13146

Please sign in to comment.