1
0
Fork 0
mirror of https://github.com/romanz/electrs.git synced 2025-02-24 23:08:39 +01:00

Support 'blockchain.address.listunspent' Electrum RPC

This commit is contained in:
Roman Zeyde 2018-07-22 21:26:02 +03:00
parent 321d655d7a
commit b83b0718dd
No known key found for this signature in database
GPG key ID: 87CAE5FA46917CBB

View file

@ -1,5 +1,6 @@
use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::transaction::Transaction;
use bitcoin::network::serialize::{deserialize, serialize}; use bitcoin::network::serialize::{deserialize, serialize};
use bitcoin::util::address::Address;
use bitcoin::util::hash::Sha256dHash; use bitcoin::util::hash::Sha256dHash;
use error_chain::ChainedError; use error_chain::ChainedError;
use hex; use hex;
@ -7,12 +8,14 @@ use serde_json::{from_str, Number, Value};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{BufRead, BufReader, Write}; use std::io::{BufRead, BufReader, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream}; use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::str::FromStr;
use std::sync::mpsc::{Sender, SyncSender, TrySendError}; use std::sync::mpsc::{Sender, SyncSender, TrySendError};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use index::compute_script_hash;
use metrics::{Gauge, HistogramOpts, HistogramVec, MetricOpts, Metrics}; use metrics::{Gauge, HistogramOpts, HistogramVec, MetricOpts, Metrics};
use query::Query; use query::{Query, Status};
use util::{spawn_thread, Channel, HeaderEntry, SyncChannel}; use util::{spawn_thread, Channel, HeaderEntry, SyncChannel};
use errors::*; use errors::*;
@ -31,6 +34,23 @@ fn usize_from_value(val: Option<&Value>, name: &str) -> Result<usize> {
Ok(val as usize) Ok(val as usize)
} }
fn unspent_from_status(status: &Status) -> Value {
json!(Value::Array(
status
.unspent()
.into_iter()
.map(|out| {
json!({
"height": out.height,
"tx_pos": out.output_index,
"tx_hash": out.txn_id.be_hex_string(),
"value": out.value,
})
})
.collect()
))
}
fn jsonify_header(entry: &HeaderEntry) -> Value { fn jsonify_header(entry: &HeaderEntry) -> Value {
let header = entry.header(); let header = entry.header();
json!({ json!({
@ -166,21 +186,18 @@ impl Connection {
fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> { fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> {
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?; let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
let status = self.query.status(&script_hash[..])?; Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
Ok(json!(Value::Array( }
status
.unspent() fn blockchain_address_listunspent(&self, params: &[Value]) -> Result<Value> {
.into_iter() let address = params
.map(|out| { .get(0)
json!({ .chain_err(|| "no address")?
"height": out.height, .as_str()
"tx_pos": out.output_index, .chain_err(|| "non-string address")?;
"tx_hash": out.txn_id.be_hex_string(), let addr = Address::from_str(address).chain_err(|| format!("invalid address {}", address))?;
"value": out.value, let script_hash = compute_script_hash(&addr.script_pubkey().into_vec());
}) Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
})
.collect()
)))
} }
fn blockchain_transaction_broadcast(&self, params: &[Value]) -> Result<Value> { fn blockchain_transaction_broadcast(&self, params: &[Value]) -> Result<Value> {
@ -231,6 +248,7 @@ impl Connection {
"blockchain.block.get_header" => self.blockchain_block_get_header(&params), "blockchain.block.get_header" => self.blockchain_block_get_header(&params),
"blockchain.estimatefee" => self.blockchain_estimatefee(&params), "blockchain.estimatefee" => self.blockchain_estimatefee(&params),
"blockchain.relayfee" => self.blockchain_relayfee(), "blockchain.relayfee" => self.blockchain_relayfee(),
"blockchain.address.listunspent" => self.blockchain_address_listunspent(&params),
"blockchain.scripthash.subscribe" => self.blockchain_scripthash_subscribe(&params), "blockchain.scripthash.subscribe" => self.blockchain_scripthash_subscribe(&params),
"blockchain.scripthash.get_balance" => self.blockchain_scripthash_get_balance(&params), "blockchain.scripthash.get_balance" => self.blockchain_scripthash_get_balance(&params),
"blockchain.scripthash.get_history" => self.blockchain_scripthash_get_history(&params), "blockchain.scripthash.get_history" => self.blockchain_scripthash_get_history(&params),