diff --git a/src/config.rs b/src/config.rs index d23128e91..a9cf5bd48 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use stderrlog; -use crate::chain::Network; +use crate::chain::{Network, Txid}; use crate::daemon::CookieGetter; use crate::errors::*; @@ -71,6 +71,8 @@ pub struct Config { pub parent_network: BNetwork, #[cfg(feature = "liquid")] pub asset_db_path: Option, + #[cfg(feature = "liquid")] + pub initial_issuance_prevout: Option, #[cfg(feature = "electrum-discovery")] pub electrum_public_hosts: Option, @@ -279,6 +281,12 @@ impl Config { .long("asset-db-path") .help("Directory for liquid/elements asset db") .takes_value(true), + ) + .arg( + Arg::with_name("initial_issuance_prevout") + .long("initial-issuance-prevout") + .help("Custom initial issuance prevout TXID (required for custom liquid testnets/signets)") + .takes_value(true), ); #[cfg(feature = "electrum-discovery")] @@ -318,6 +326,12 @@ impl Config { #[cfg(feature = "liquid")] let asset_db_path = m.value_of("asset_db_path").map(PathBuf::from); + #[cfg(feature = "liquid")] + let initial_issuance_prevout = m.value_of("initial_issuance_prevout").map(|s| { + s.parse::() + .expect("invalid initial-issuance-prevout TXID") + }); + let default_daemon_port = match network_type { #[cfg(not(feature = "liquid"))] Network::Bitcoin => 8332, @@ -497,6 +511,8 @@ impl Config { parent_network, #[cfg(feature = "liquid")] asset_db_path, + #[cfg(feature = "liquid")] + initial_issuance_prevout, #[cfg(feature = "electrum-discovery")] electrum_public_hosts, @@ -505,6 +521,12 @@ impl Config { #[cfg(feature = "electrum-discovery")] tor_proxy: m.value_of("tor_proxy").map(|s| s.parse().unwrap()), }; + + #[cfg(feature = "liquid")] + if let Some(txid) = config.initial_issuance_prevout { + crate::util::transaction::set_custom_initial_issuance_prevout(txid); + } + eprintln!("{:?}", config); config } diff --git a/src/util/mod.rs b/src/util/mod.rs index d5e8f1be8..179ed989c 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,6 +1,6 @@ mod block; mod script; -mod transaction; +pub mod transaction; pub mod bincode; pub mod electrum_merkle; diff --git a/src/util/transaction.rs b/src/util/transaction.rs index c63e070e0..910f1dea8 100644 --- a/src/util/transaction.rs +++ b/src/util/transaction.rs @@ -3,6 +3,9 @@ use crate::util::BlockId; use std::collections::{BTreeSet, HashMap}; +#[cfg(feature = "liquid")] +use std::sync::RwLock; + #[cfg(feature = "liquid")] lazy_static! { static ref REGTEST_INITIAL_ISSUANCE_PREVOUT: Txid = @@ -13,6 +16,14 @@ lazy_static! { "0c52d2526a5c9f00e9fb74afd15dd3caaf17c823159a514f929ae25193a43a52" .parse() .unwrap(); + // Ref. https://github.com/Blockstream/electrs/issues/125 + static ref CUSTOM_INITIAL_ISSUANCE_PREVOUT: RwLock> = RwLock::new(None); +} + +#[cfg(feature = "liquid")] +pub fn set_custom_initial_issuance_prevout(txid: Txid) { + let mut lock = CUSTOM_INITIAL_ISSUANCE_PREVOUT.write().unwrap(); + *lock = Some(txid); } #[derive(Serialize, Deserialize, Debug)] @@ -77,11 +88,27 @@ pub fn is_coinbase(txin: &TxIn) -> bool { pub fn has_prevout(txin: &TxIn) -> bool { #[cfg(not(feature = "liquid"))] return !txin.previous_output.is_null(); + #[cfg(feature = "liquid")] - return !txin.is_coinbase() - && !txin.is_pegin - && txin.previous_output.txid != *REGTEST_INITIAL_ISSUANCE_PREVOUT - && txin.previous_output.txid != *TESTNET_INITIAL_ISSUANCE_PREVOUT; + { + // 1. Check standard liquid conditions + if txin.is_coinbase() || txin.is_pegin { + return false; + } + + // 2. Check against the CUSTOM dummy prevout passed from Config + if let Ok(lock) = CUSTOM_INITIAL_ISSUANCE_PREVOUT.read() { + if let Some(custom_txid) = *lock { + if txin.previous_output.txid == custom_txid { + return false; // Ignore this input! + } + } + } + + // 3. Check against hardcoded defaults + return txin.previous_output.txid != *REGTEST_INITIAL_ISSUANCE_PREVOUT + && txin.previous_output.txid != *TESTNET_INITIAL_ISSUANCE_PREVOUT; + } } pub fn is_spendable(txout: &TxOut) -> bool { @@ -203,4 +230,4 @@ mod test { Some(value) ); } -} +} \ No newline at end of file