1
0
Fork 0
mirror of https://github.com/romanz/electrs.git synced 2025-02-24 15:02:21 +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::network::serialize::{deserialize, serialize};
use bitcoin::util::address::Address;
use bitcoin::util::hash::Sha256dHash;
use error_chain::ChainedError;
use hex;
@ -7,12 +8,14 @@ use serde_json::{from_str, Number, Value};
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::str::FromStr;
use std::sync::mpsc::{Sender, SyncSender, TrySendError};
use std::sync::{Arc, Mutex};
use std::thread;
use index::compute_script_hash;
use metrics::{Gauge, HistogramOpts, HistogramVec, MetricOpts, Metrics};
use query::Query;
use query::{Query, Status};
use util::{spawn_thread, Channel, HeaderEntry, SyncChannel};
use errors::*;
@ -31,6 +34,23 @@ fn usize_from_value(val: Option<&Value>, name: &str) -> Result<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 {
let header = entry.header();
json!({
@ -166,21 +186,18 @@ impl Connection {
fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> {
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
let status = self.query.status(&script_hash[..])?;
Ok(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()
)))
Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
}
fn blockchain_address_listunspent(&self, params: &[Value]) -> Result<Value> {
let address = params
.get(0)
.chain_err(|| "no address")?
.as_str()
.chain_err(|| "non-string address")?;
let addr = Address::from_str(address).chain_err(|| format!("invalid address {}", address))?;
let script_hash = compute_script_hash(&addr.script_pubkey().into_vec());
Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
}
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.estimatefee" => self.blockchain_estimatefee(&params),
"blockchain.relayfee" => self.blockchain_relayfee(),
"blockchain.address.listunspent" => self.blockchain_address_listunspent(&params),
"blockchain.scripthash.subscribe" => self.blockchain_scripthash_subscribe(&params),
"blockchain.scripthash.get_balance" => self.blockchain_scripthash_get_balance(&params),
"blockchain.scripthash.get_history" => self.blockchain_scripthash_get_history(&params),