Skip to content

Commit

Permalink
Don't deserialize transaction bytes in blockchain.transaction.get RPC
Browse files Browse the repository at this point in the history
Simplify `bsl::FindTransaction` to return the serialized transaction.
  • Loading branch information
romanz committed Dec 26, 2024
1 parent b2ab18a commit b224d34
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 12 deletions.
9 changes: 5 additions & 4 deletions src/electrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,20 +374,21 @@ impl Rpc {
.map(|(blockhash, _tx)| blockhash);
return self.daemon.get_transaction_info(&txid, blockhash);
}
// if the scripthash was subscribed, tx should be cached
if let Some(tx_hex) = self
.cache
.get_tx(&txid, |tx_bytes| tx_bytes.to_lower_hex_string())
{
return Ok(json!(tx_hex));
}
debug!("tx cache miss: txid={}", txid);
// use internal index to load confirmed transaction without an RPC
if let Some(tx) = self
// use internal index to load confirmed transaction
if let Some(tx_hex) = self
.tracker
.lookup_transaction(&self.daemon, txid)?
.map(|(_blockhash, tx)| tx)
.map(|(_blockhash, tx)| tx.to_lower_hex_string())
{
return Ok(json!(serialize_hex(&tx)));
return Ok(json!(tx_hex));
}
// load unconfirmed transaction via RPC
Ok(json!(self.daemon.get_transaction_hex(&txid, None)?))
Expand Down
36 changes: 28 additions & 8 deletions src/tracker.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::ops::ControlFlow;

use anyhow::{Context, Result};
use bitcoin::{BlockHash, Transaction, Txid};
use bitcoin_slices::{
bsl::{self, FindTransaction},
Error::VisitBreak,
Visit,
};
use bitcoin::{BlockHash, Txid};
use bitcoin_slices::{bsl, Error::VisitBreak, Visit, Visitor};

use crate::{
cache::Cache,
Expand All @@ -17,6 +15,7 @@ use crate::{
metrics::Metrics,
signals::ExitFlag,
status::{Balance, ScriptHashStatus, UnspentEntry},
types::bsl_txid,
};

/// Electrum protocol subscriptions' tracker
Expand Down Expand Up @@ -106,7 +105,7 @@ impl Tracker {
&self,
daemon: &Daemon,
txid: Txid,
) -> Result<Option<(BlockHash, Transaction)>> {
) -> Result<Option<(BlockHash, Box<[u8]>)>> {
// Note: there are two blocks with coinbase transactions having same txid (see BIP-30)
let blockhashes = self.index.filter_by_txid(txid);
let mut result = None;
Expand All @@ -116,10 +115,31 @@ impl Tracker {
}
let mut visitor = FindTransaction::new(txid);
result = match bsl::Block::visit(&block, &mut visitor) {
Ok(_) | Err(VisitBreak) => visitor.tx_found().map(|tx| (blockhash, tx)),
Ok(_) | Err(VisitBreak) => visitor.found.map(|tx| (blockhash, tx)),
Err(e) => panic!("core returned invalid block: {:?}", e),
};
})?;
Ok(result)
}
}

pub struct FindTransaction {
txid: bitcoin::Txid,
found: Option<Box<[u8]>>, // no need to deserialize
}

impl FindTransaction {
pub fn new(txid: bitcoin::Txid) -> Self {
Self { txid, found: None }
}
}
impl Visitor for FindTransaction {
fn visit_transaction(&mut self, tx: &bsl::Transaction) -> ControlFlow<()> {
if self.txid == bsl_txid(tx) {
self.found = Some(tx.as_ref().into());
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
}
}

0 comments on commit b224d34

Please sign in to comment.