diff --git a/src/daemon.rs b/src/daemon.rs index 6c375d3..22389d5 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -624,8 +624,8 @@ impl Daemon { let header = self .getblockheader(&blockhash) .chain_err(|| format!("failed to get {} header", blockhash))?; - new_headers.push(header); blockhash = header.prev_blockhash; + new_headers.push(header); } trace!("downloaded {} block headers", new_headers.len()); new_headers.reverse(); // so the tip is the last vector entry diff --git a/src/new_index/mempool.rs b/src/new_index/mempool.rs index 1a0db17..85d11d3 100644 --- a/src/new_index/mempool.rs +++ b/src/new_index/mempool.rs @@ -123,14 +123,25 @@ impl Mempool { } match entry { + #[cfg(not(feature="liquid"))] TxHistoryInfo::Funding(info) => { stats.funded_txo_count += 1; stats.funded_txo_sum += info.value; } + #[cfg(feature="liquid")] + TxHistoryInfo::Funding(_) => { + stats.funded_txo_count += 1; + } + + #[cfg(not(feature="liquid"))] TxHistoryInfo::Spending(info) => { stats.spent_txo_count += 1; stats.spent_txo_sum += info.value; } + #[cfg(feature="liquid")] + TxHistoryInfo::Spending(_) => { + stats.spent_txo_count += 1; + } }; } diff --git a/src/new_index/schema.rs b/src/new_index/schema.rs index 0c0d322..7c56772 100644 --- a/src/new_index/schema.rs +++ b/src/new_index/schema.rs @@ -7,6 +7,9 @@ use crypto::sha2::Sha256; use itertools::Itertools; use rayon::prelude::*; +#[cfg(feature="liquid")] +use elements::confidential::Value; + use std::collections::{BTreeSet, HashMap, HashSet}; use std::path::Path; use std::sync::{Arc, RwLock}; @@ -16,7 +19,7 @@ use crate::daemon::Daemon; use crate::errors::*; use crate::metrics::{HistogramOpts, HistogramTimer, HistogramVec, Metrics}; use crate::util::{ - full_hash, BlockHeaderMeta, BlockMeta, BlockStatus, Bytes, HeaderEntry, HeaderList, + is_coinbase, full_hash, BlockHeaderMeta, BlockMeta, BlockStatus, Bytes, HeaderEntry, HeaderList, }; use crate::new_index::db::{DBFlush, DBRow, ScanIterator, DB}; @@ -77,8 +80,11 @@ impl From<&HeaderEntry> for BlockId { pub struct Utxo { pub txid: Sha256dHash, pub vout: u32, - pub value: u64, pub confirmed: Option, + #[cfg(not(feature="liquid"))] + pub value: u64, + #[cfg(feature="liquid")] + pub value: Value, } impl From<&Utxo> for OutPoint { @@ -98,8 +104,10 @@ pub struct SpendingInput { pub struct ScriptStats { pub tx_count: usize, pub funded_txo_count: usize, - pub funded_txo_sum: u64, pub spent_txo_count: usize, + #[cfg(not(feature="liquid"))] + pub funded_txo_sum: u64, + #[cfg(not(feature="liquid"))] pub spent_txo_sum: u64, } @@ -108,8 +116,10 @@ impl ScriptStats { ScriptStats { tx_count: 0, funded_txo_count: 0, - funded_txo_sum: 0, spent_txo_count: 0, + #[cfg(not(feature="liquid"))] + funded_txo_sum: 0, + #[cfg(not(feature="liquid"))] spent_txo_sum: 0, } } @@ -427,14 +437,25 @@ impl ChainQuery { } match history.key.txinfo { + #[cfg(not(feature="liquid"))] TxHistoryInfo::Funding(ref info) => { stats.funded_txo_count += 1; stats.funded_txo_sum += info.value; } + #[cfg(feature="liquid")] + TxHistoryInfo::Funding(_) => { + stats.funded_txo_count += 1; + } + + #[cfg(not(feature="liquid"))] TxHistoryInfo::Spending(ref info) => { stats.spent_txo_count += 1; stats.spent_txo_sum += info.value; } + #[cfg(feature="liquid")] + TxHistoryInfo::Spending(_) => { + stats.spent_txo_count += 1; + } }; lastblock = Some(blockid.hash); @@ -636,7 +657,7 @@ fn get_previous_txos(block_entries: &[BlockEntry]) -> BTreeSet { .flat_map(|b| { b.block.txdata.iter().flat_map(|tx| { tx.input.iter().filter_map(|txin| { - if txin.previous_output.is_null() { + if is_coinbase(txin) { None } else { Some(txin.previous_output) @@ -718,7 +739,7 @@ fn index_transaction( } } for (txi_index, txi) in tx.input.iter().enumerate() { - if txi.previous_output.is_null() { + if is_coinbase(txi) { continue; } let prev_txo = previous_txos_map @@ -955,7 +976,10 @@ impl BlockRow { pub struct FundingInfo { pub txid: FullHash, // funding transaction pub vout: u16, + #[cfg(not(feature="liquid"))] pub value: u64, + #[cfg(feature="liquid")] + pub value: Value, } #[derive(Serialize, Deserialize)] @@ -964,7 +988,10 @@ pub struct SpendingInfo { pub vin: u16, pub prev_txid: FullHash, // funding transaction pub prev_vout: u16, + #[cfg(not(feature="liquid"))] pub value: u64, + #[cfg(feature="liquid")] + pub value: Value, } #[derive(Serialize, Deserialize)] diff --git a/src/rest.rs b/src/rest.rs index 03a36ef..d7fe115 100644 --- a/src/rest.rs +++ b/src/rest.rs @@ -3,7 +3,7 @@ use crate::config::Config; use crate::errors; use crate::new_index::{compute_script_hash, BlockId, Query, SpendingInput, Utxo}; use crate::util::{ - full_hash, get_script_asm, script_to_address, BlockHeaderMeta, FullHash, TransactionStatus, + is_coinbase, full_hash, get_script_asm, script_to_address, BlockHeaderMeta, FullHash, TransactionStatus, }; use bitcoin::consensus::encode::{self, serialize}; @@ -17,6 +17,9 @@ use hyper::rt::{self, Future}; use hyper::service::service_fn_ok; use hyper::{Body, Method, Request, Response, Server, StatusCode}; +#[cfg(feature="liquid")] +use elements::confidential::Value; + use serde::Serialize; use serde_json; use std::collections::BTreeMap; @@ -39,13 +42,15 @@ struct BlockValue { height: u32, version: u32, timestamp: u32, - bits: u32, - nonce: u32, tx_count: u32, size: u32, weight: u32, merkle_root: String, previousblockhash: Option, + #[cfg(not(feature="liquid"))] + nonce: u32, + #[cfg(not(feature="liquid"))] + bits: u32, } impl From for BlockValue { @@ -56,8 +61,6 @@ impl From for BlockValue { height: blockhm.header_entry.height() as u32, version: header.version, timestamp: header.time, - bits: header.bits, - nonce: header.nonce, tx_count: blockhm.meta.tx_count, size: blockhm.meta.size, weight: blockhm.meta.weight, @@ -67,6 +70,11 @@ impl From for BlockValue { } else { None }, + + #[cfg(not(feature="liquid"))] + bits: header.bits, + #[cfg(not(feature="liquid"))] + nonce: header.nonce, } } } @@ -134,12 +142,17 @@ struct TxInValue { impl From for TxInValue { fn from(txin: TxIn) -> Self { - let script = txin.script_sig; + #[cfg(not(feature="liquid"))] let witness = if txin.witness.len() > 0 { Some(txin.witness.iter().map(|w| hex::encode(w)).collect()) } else { None }; + #[cfg(feature="liquid")] + let witness = None; // @TODO + + let is_coinbase = is_coinbase(&txin); + let script = txin.script_sig; TxInValue { txid: txin.previous_output.txid, @@ -147,8 +160,8 @@ impl From for TxInValue { prevout: None, // added later scriptsig_asm: get_script_asm(&script), scriptsig: script, - witness: witness, - is_coinbase: txin.previous_output.is_null(), + witness, + is_coinbase, sequence: txin.sequence, } } @@ -158,14 +171,33 @@ impl From for TxInValue { struct TxOutValue { scriptpubkey: Script, scriptpubkey_asm: String, - value: u64, scriptpubkey_address: Option, scriptpubkey_type: String, + + #[cfg(not(feature="liquid"))] + value: u64, + #[cfg(feature="liquid")] + value: Option, + #[cfg(feature="liquid")] + valuecommitment: Option, } impl From for TxOutValue { fn from(txout: TxOut) -> Self { + #[cfg(not(feature="liquid"))] let value = txout.value; + + #[cfg(feature="liquid")] + let value = match txout.value { + Value::Explicit(value) => Some(value), + _ => None, + }; + #[cfg(feature="liquid")] + let valuecommitment = match txout.value { + Value::Confidential(..) => Some(hex::encode(serialize(&txout.value))), + _ => None, + }; + let script = txout.script_pubkey; let script_asm = get_script_asm(&script); @@ -195,6 +227,8 @@ impl From for TxOutValue { scriptpubkey_address: None, // added later scriptpubkey_type: script_type.to_string(), value, + #[cfg(feature="liquid")] + valuecommitment, } } } @@ -203,17 +237,37 @@ impl From for TxOutValue { struct UtxoValue { txid: Sha256dHash, vout: u32, - value: u64, status: TransactionStatus, + #[cfg(not(feature="liquid"))] + value: u64, + #[cfg(feature="liquid")] + value: Option, + #[cfg(feature="liquid")] + valuecommitment: Option, } impl From for UtxoValue { fn from(utxo: Utxo) -> Self { + #[cfg(not(feature="liquid"))] + let value = utxo.value; + + #[cfg(feature="liquid")] + let value = match utxo.value { + Value::Explicit(value) => Some(value), + _ => None, + }; + #[cfg(feature="liquid")] + let valuecommitment = match utxo.value { + Value::Confidential(..) => Some(hex::encode(serialize(&utxo.value))), + _ => None, + }; + UtxoValue { txid: utxo.txid, vout: utxo.vout, - value: utxo.value, + value, status: TransactionStatus::from(utxo.confirmed), - // utxo.script is also available but is unused here + #[cfg(feature="liquid")] + valuecommitment, } } } @@ -307,19 +361,21 @@ fn attach_txs_data(txs: &mut Vec, config: &Config, query: &Que } // attach tx fee - if config.prevout_enabled { - for mut tx in txs.iter_mut() { - if tx.vin.iter().any(|vin| vin.prevout.is_none()) { - continue; - } + #[cfg(not(feature="liquid"))] { + if config.prevout_enabled { + for mut tx in txs.iter_mut() { + if tx.vin.iter().any(|vin| vin.prevout.is_none()) { + continue; + } - let total_in: u64 = tx - .vin - .iter() - .map(|vin| vin.clone().prevout.unwrap().value) - .sum(); - let total_out: u64 = tx.vout.iter().map(|vout| vout.value).sum(); - tx.fee = Some(total_in - total_out); + let total_in: u64 = tx + .vin + .iter() + .map(|vin| vin.clone().prevout.unwrap().value) + .sum(); + let total_out: u64 = tx.vout.iter().map(|vout| vout.value).sum(); + tx.fee = Some(total_in - total_out); + } } } } diff --git a/src/util.rs b/src/util.rs index 1845f24..7244abc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -use crate::chain::{Block, BlockHeader}; +use crate::chain::{Block, BlockHeader, TxIn}; use crate::errors::*; use crate::new_index::{BlockEntry, BlockId}; @@ -433,3 +433,10 @@ pub fn get_script_asm(script: &Script) -> String { let asm = format!("{:?}", script); (&asm[7..asm.len() - 1]).to_string() } + +pub fn is_coinbase(txin: &TxIn) -> bool { + #[cfg(not(feature="liquid"))] + return txin.previous_output.is_null(); + #[cfg(feature="liquid")] + return txin.is_coinbase(); +}