Browse Source

Implement "verbose" `blockchain.transaction.get` Electrum RPC

Also, change Daemon::load_txn() to be a private method.
refactor-mempool
Roman Zeyde 7 years ago
parent
commit
7e7f62111a
No known key found for this signature in database GPG Key ID: 87CAE5FA46917CBB
  1. 58
      src/query.rs
  2. 8
      src/rpc.rs

58
src/query.rs

@ -11,6 +11,7 @@ use app::App;
use index::{compute_script_hash, TxInRow, TxOutRow, TxRow}; use index::{compute_script_hash, TxInRow, TxOutRow, TxRow};
use mempool::Tracker; use mempool::Tracker;
use metrics::Metrics; use metrics::Metrics;
use serde_json::Value;
use store::{ReadStore, Row}; use store::{ReadStore, Row};
use util::{FullHash, HashPrefix, HeaderEntry}; use util::{FullHash, HashPrefix, HeaderEntry};
@ -204,7 +205,7 @@ impl Query {
let txid: Sha256dHash = deserialize(&tx_row.key.txid).unwrap(); let txid: Sha256dHash = deserialize(&tx_row.key.txid).unwrap();
let txn = self let txn = self
.tx_cache .tx_cache
.get_or_else(&txid, || self.load_txn(&txid, Some(tx_row.height)))?; .get_or_else(&txid, || self.load_txn(&txid, tx_row.height))?;
txns.push(TxnHeight { txns.push(TxnHeight {
txn, txn,
height: tx_row.height, height: tx_row.height,
@ -315,30 +316,45 @@ impl Query {
Ok(Status { confirmed, mempool }) Ok(Status { confirmed, mempool })
} }
pub fn load_txn( fn lookup_confirmed_blockhash(
&self, &self,
tx_hash: &Sha256dHash, tx_hash: &Sha256dHash,
block_height: Option<u32>, block_height: Option<u32>,
) -> Result<Transaction> { ) -> Result<Option<Sha256dHash>> {
if let Some(txn) = self.tracker.read().unwrap().get_txn(&tx_hash) { let blockhash = if self.tracker.read().unwrap().get_txn(&tx_hash).is_some() {
return Ok(txn); // found in mempool (as unconfirmed transaction) None // found in mempool (as unconfirmed transaction)
} } else {
let height = match block_height { // Lookup in confirmed transactions' index
Some(height) => height, let height = match block_height {
None => { Some(height) => height,
// Lookup in confirmed transactions' index None => {
txrow_by_txid(self.app.read_store(), &tx_hash) txrow_by_txid(self.app.read_store(), &tx_hash)
.chain_err(|| format!("not indexed tx {}", tx_hash))? .chain_err(|| format!("not indexed tx {}", tx_hash))?
.height .height
} }
};
let header = self
.app
.index()
.get_header(height as usize)
.chain_err(|| format!("missing header at height {}", height))?;
Some(*header.hash())
}; };
let blockhash = *self Ok(blockhash)
.app }
.index()
.get_header(height as usize) // Internal API for transaction retrieval
.chain_err(|| format!("missing header at height {}", height))? fn load_txn(&self, tx_hash: &Sha256dHash, block_height: u32) -> Result<Transaction> {
.hash(); let blockhash = self.lookup_confirmed_blockhash(tx_hash, Some(block_height))?;
self.app.daemon().gettransaction(tx_hash, Some(blockhash)) self.app.daemon().gettransaction(tx_hash, blockhash)
}
// Public API for transaction retrieval (for Electrum RPC)
pub fn get_transaction(&self, tx_hash: &Sha256dHash, verbose: bool) -> Result<Value> {
let blockhash = self.lookup_confirmed_blockhash(tx_hash, /*block_height*/ None)?;
self.app
.daemon()
.gettransaction_raw(tx_hash, blockhash, verbose)
} }
pub fn get_headers(&self, heights: &[usize]) -> Vec<HeaderEntry> { pub fn get_headers(&self, heights: &[usize]) -> Vec<HeaderEntry> {

8
src/rpc.rs

@ -223,10 +223,12 @@ impl Connection {
} }
fn blockchain_transaction_get(&self, params: &[Value]) -> Result<Value> { fn blockchain_transaction_get(&self, params: &[Value]) -> Result<Value> {
// TODO: handle 'verbose' param
let tx_hash = hash_from_value(params.get(0)).chain_err(|| "bad tx_hash")?; let tx_hash = hash_from_value(params.get(0)).chain_err(|| "bad tx_hash")?;
let tx = self.query.load_txn(&tx_hash, /*blockhash=*/ None)?; let verbose = match params.get(1) {
Ok(json!(hex::encode(&serialize(&tx).unwrap()))) Some(value) => value.as_bool().chain_err(|| "non-bool verbose value")?,
None => false,
};
Ok(self.query.get_transaction(&tx_hash, verbose)?)
} }
fn blockchain_transaction_get_merkle(&self, params: &[Value]) -> Result<Value> { fn blockchain_transaction_get_merkle(&self, params: &[Value]) -> Result<Value> {

Loading…
Cancel
Save