liquid: Add preliminary conditional support for Elements data structures
This makes the code properly compile with the "liquid" feature flag enabled, but it is still broken in all sorts of ways and missing some functionality.
This commit is contained in:
parent
dbceb53634
commit
b455f5c026
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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<BlockId>,
|
||||
#[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<OutPoint> {
|
||||
.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)]
|
||||
|
||||
104
src/rest.rs
104
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<String>,
|
||||
#[cfg(not(feature="liquid"))]
|
||||
nonce: u32,
|
||||
#[cfg(not(feature="liquid"))]
|
||||
bits: u32,
|
||||
}
|
||||
|
||||
impl From<BlockHeaderMeta> for BlockValue {
|
||||
@ -56,8 +61,6 @@ impl From<BlockHeaderMeta> 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<BlockHeaderMeta> 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<TxIn> 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<TxIn> 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<TxIn> for TxInValue {
|
||||
struct TxOutValue {
|
||||
scriptpubkey: Script,
|
||||
scriptpubkey_asm: String,
|
||||
value: u64,
|
||||
scriptpubkey_address: Option<String>,
|
||||
scriptpubkey_type: String,
|
||||
|
||||
#[cfg(not(feature="liquid"))]
|
||||
value: u64,
|
||||
#[cfg(feature="liquid")]
|
||||
value: Option<u64>,
|
||||
#[cfg(feature="liquid")]
|
||||
valuecommitment: Option<String>,
|
||||
}
|
||||
|
||||
impl From<TxOut> 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<TxOut> for TxOutValue {
|
||||
scriptpubkey_address: None, // added later
|
||||
scriptpubkey_type: script_type.to_string(),
|
||||
value,
|
||||
#[cfg(feature="liquid")]
|
||||
valuecommitment,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -203,17 +237,37 @@ impl From<TxOut> for TxOutValue {
|
||||
struct UtxoValue {
|
||||
txid: Sha256dHash,
|
||||
vout: u32,
|
||||
value: u64,
|
||||
status: TransactionStatus,
|
||||
#[cfg(not(feature="liquid"))]
|
||||
value: u64,
|
||||
#[cfg(feature="liquid")]
|
||||
value: Option<u64>,
|
||||
#[cfg(feature="liquid")]
|
||||
valuecommitment: Option<String>,
|
||||
}
|
||||
impl From<Utxo> 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<TransactionValue>, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user