From 537e85f2dbe1b2f43233705631abe73a7cf994f2 Mon Sep 17 00:00:00 2001 From: Dagur Valberg Johannsson Date: Fri, 14 Dec 2018 11:29:28 +0100 Subject: [PATCH] Implement 'blockchain.transaction.id_from_pos' --- src/query.rs | 24 ++++++++++++++++++++++++ src/rpc.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/query.rs b/src/query.rs index 7d14f78..d7e4f95 100644 --- a/src/query.rs +++ b/src/query.rs @@ -406,6 +406,30 @@ impl Query { Ok((branch, pos)) } + pub fn get_id_from_pos( + &self, + height: usize, + tx_pos: usize, + want_merkle: bool, + ) -> Result<(Sha256dHash, Vec)> { + let header_entry = self + .app + .index() + .get_header(height) + .chain_err(|| format!("missing block #{}", height))?; + + let txids = self.app.daemon().getblocktxids(&header_entry.hash())?; + let txid = *txids + .get(tx_pos) + .chain_err(|| format!("No tx in position #{} in block #{}", tx_pos, height))?; + + if want_merkle { + let (branches, _root) = create_merkle_branch_and_root(txids, tx_pos); + return Ok((txid, branches)); + } + return Ok((txid, [].to_vec())); + } + pub fn broadcast(&self, txn: &Transaction) -> Result { self.app.daemon().broadcast(txn) } diff --git a/src/rpc.rs b/src/rpc.rs index 8da32b5..c0833bd 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -33,6 +33,12 @@ fn usize_from_value(val: Option<&Value>, name: &str) -> Result { Ok(val as usize) } +fn bool_from_value(val: Option<&Value>, name: &str) -> Result { + let val = val.chain_err(|| format!("missing {}", name))?; + let val = val.as_bool().chain_err(|| format!("not a bool {}", name))?; + Ok(val as bool) +} + fn unspent_from_status(status: &Status) -> Value { json!(Value::Array( status @@ -283,6 +289,30 @@ impl Connection { "pos": pos})) } + fn blockchain_transaction_id_from_pos(&self, params: &[Value]) -> Result { + let height = usize_from_value(params.get(0), "height")?; + let tx_pos = usize_from_value(params.get(1), "tx_pos")?; + let mut want_merkle = false; + if params.len() > 2 { + want_merkle = bool_from_value(params.get(2), "merkle")?; + } + + let (txid, merkle) = self.query.get_id_from_pos(height, tx_pos, want_merkle)?; + + if !want_merkle { + return Ok(json!(txid.be_hex_string())); + } + + let merkle_vec: Vec = merkle + .into_iter() + .map(|entry| entry.be_hex_string()) + .collect(); + + Ok(json!({ + "tx_id" : txid.be_hex_string(), + "merkle" : merkle_vec})) + } + fn handle_command(&mut self, method: &str, params: &[Value], id: &Number) -> Result { let timer = self .stats @@ -307,6 +337,9 @@ impl Connection { "blockchain.transaction.broadcast" => self.blockchain_transaction_broadcast(¶ms), "blockchain.transaction.get" => self.blockchain_transaction_get(¶ms), "blockchain.transaction.get_merkle" => self.blockchain_transaction_get_merkle(¶ms), + "blockchain.transaction.id_from_pos" => { + self.blockchain_transaction_id_from_pos(¶ms) + } "mempool.get_fee_histogram" => self.mempool_get_fee_histogram(), "server.banner" => self.server_banner(), "server.donation_address" => self.server_donation_address(),