mirror of
https://github.com/romanz/electrs.git
synced 2025-02-24 06:57:53 +01:00
Fix txid
index collision handling
This commit is contained in:
parent
6f301a0167
commit
ca2841f432
2 changed files with 38 additions and 13 deletions
|
@ -356,18 +356,26 @@ impl Rpc {
|
||||||
fn transaction_get(&self, args: &TxGetArgs) -> Result<Value> {
|
fn transaction_get(&self, args: &TxGetArgs) -> Result<Value> {
|
||||||
let (txid, verbose) = args.into();
|
let (txid, verbose) = args.into();
|
||||||
if verbose {
|
if verbose {
|
||||||
let blockhash = self.tracker.get_blockhash_by_txid(txid);
|
let blockhash = self
|
||||||
|
.tracker
|
||||||
|
.lookup_transaction(&self.daemon, txid)?
|
||||||
|
.map(|(blockhash, _tx)| blockhash);
|
||||||
return self.daemon.get_transaction_info(&txid, blockhash);
|
return self.daemon.get_transaction_info(&txid, blockhash);
|
||||||
}
|
}
|
||||||
let cached = self.cache.get_tx(&txid, |tx| serialize(tx).to_hex());
|
if let Some(tx) = self.cache.get_tx(&txid, |tx| serialize(tx)) {
|
||||||
Ok(match cached {
|
return Ok(json!(tx.to_hex()));
|
||||||
Some(tx_hex) => json!(tx_hex),
|
}
|
||||||
None => {
|
debug!("tx cache miss: txid={}", txid);
|
||||||
debug!("tx cache miss: txid={}", txid);
|
// use internal index to load confirmed transaction without an RPC
|
||||||
let blockhash = self.tracker.get_blockhash_by_txid(txid);
|
if let Some(tx) = self
|
||||||
json!(self.daemon.get_transaction_hex(&txid, blockhash)?)
|
.tracker
|
||||||
}
|
.lookup_transaction(&self.daemon, txid)?
|
||||||
})
|
.map(|(_blockhash, tx)| tx)
|
||||||
|
{
|
||||||
|
return Ok(json!(serialize(&tx).to_hex()));
|
||||||
|
}
|
||||||
|
// load unconfirmed transaction via RPC
|
||||||
|
Ok(json!(self.daemon.get_transaction_hex(&txid, None)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_get_merkle(&self, (txid, height): &(Txid, usize)) -> Result<Value> {
|
fn transaction_get_merkle(&self, (txid, height): &(Txid, usize)) -> Result<Value> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use bitcoin::{BlockHash, Txid};
|
use bitcoin::{BlockHash, Transaction, Txid};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cache::Cache,
|
cache::Cache,
|
||||||
|
@ -93,8 +93,25 @@ impl Tracker {
|
||||||
status.get_balance(self.chain())
|
status.get_balance(self.chain())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_blockhash_by_txid(&self, txid: Txid) -> Option<BlockHash> {
|
pub(crate) fn lookup_transaction(
|
||||||
|
&self,
|
||||||
|
daemon: &Daemon,
|
||||||
|
txid: Txid,
|
||||||
|
) -> Result<Option<(BlockHash, Transaction)>> {
|
||||||
// Note: there are two blocks with coinbase transactions having same txid (see BIP-30)
|
// Note: there are two blocks with coinbase transactions having same txid (see BIP-30)
|
||||||
self.index.filter_by_txid(txid).next()
|
let blockhashes = self.index.filter_by_txid(txid);
|
||||||
|
let mut result = None;
|
||||||
|
daemon.for_blocks(blockhashes, |blockhash, block| {
|
||||||
|
for tx in block.txdata {
|
||||||
|
if result.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if tx.txid() == txid {
|
||||||
|
result = Some((blockhash, tx));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue