Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
332 changes: 317 additions & 15 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ default-run = "electrs"
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_error_description_deprecated)"] }

[features]
liquid = ["elements"]
liquid = ["elements", "reqwest"]
electrum-discovery = ["electrum-client"]
bench = []
otlp-tracing = [
Expand Down Expand Up @@ -59,7 +59,7 @@ serde_json = "1.0.60"
signal-hook = "0.4"
stderrlog = "0.6"
sysconf = ">=0.3.4"
time = { version = "0.3", features = ["formatting"] }
time = { version = "0.3", features = ["formatting", "parsing"] }
tiny_http = "0.12.0"
url = "2.2.0"
hyper = { version = "1", features = ["http1", "server"] }
Expand All @@ -73,6 +73,7 @@ tracing-subscriber = { version = "0.3.17", default-features = false, features =
opentelemetry-semantic-conventions = { version = "0.12.0", optional = true }
tracing = { version = "0.1.40", default-features = false, features = ["attributes"], optional = true }
rand = "0.9.1"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"], optional = true }

# optional dependencies for electrum-discovery
electrum-client = { version = "0.8", optional = true }
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ In addition to electrs's original configuration options, a few new options are a

Additional options with the `liquid` feature:
- `--parent-network <network>` - the parent network this chain is pegged to.
- `--asset-registry-url <url>` - base URL for the Liquid asset registry v2 service.

Asset registry timeouts can be configured in milliseconds with the
`ELECTRS_ASSET_REGISTRY_CONNECT_TIMEOUT_MS` and
`ELECTRS_ASSET_REGISTRY_REQUEST_TIMEOUT_MS` environment variables. They default
to 2000 ms and 5000 ms, respectively.

Additional options with the `electrum-discovery` feature:
- `--electrum-hosts <json>` - a json map of the public hosts where the electrum server is reachable, in the [`server.features` format](https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#server-features).
Expand Down
16 changes: 9 additions & 7 deletions src/bin/electrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use electrs::{
use electrs::otlp_trace;

#[cfg(feature = "liquid")]
use electrs::elements::AssetRegistry;
use electrs::elements::RegistryClient;
use electrs::metrics::MetricOpts;

/// Default salt rotation interval in seconds (24 hours)
Expand Down Expand Up @@ -115,19 +115,21 @@ fn run_server(config: Arc<Config>, salt_rwlock: Arc<RwLock<String>>) -> Result<(
}

#[cfg(feature = "liquid")]
let asset_db = config.asset_db_path.as_ref().map(|db_dir| {
let asset_db = Arc::new(RwLock::new(AssetRegistry::new(db_dir.clone())));
AssetRegistry::spawn_sync(asset_db.clone());
asset_db
});
let asset_registry = config
.asset_registry_url
.clone()
.map(RegistryClient::new)
.transpose()
.chain_err(|| "failed creating asset registry client")?
.map(Arc::new);

let query = Arc::new(Query::new(
Arc::clone(&chain),
Arc::clone(&mempool),
Arc::clone(&daemon),
Arc::clone(&config),
#[cfg(feature = "liquid")]
asset_db,
asset_registry,
));

// TODO: configuration for which servers to start
Expand Down
21 changes: 15 additions & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
use stderrlog;
#[cfg(feature = "liquid")]
use url::Url;

use crate::chain::Network;
use crate::daemon::CookieGetter;
Expand Down Expand Up @@ -86,7 +88,7 @@ pub struct Config {
#[cfg(feature = "liquid")]
pub parent_network: BNetwork,
#[cfg(feature = "liquid")]
pub asset_db_path: Option<PathBuf>,
pub asset_registry_url: Option<Url>,

#[cfg(feature = "electrum-discovery")]
pub electrum_public_hosts: Option<crate::electrum::ServerHosts>,
Expand Down Expand Up @@ -328,9 +330,9 @@ impl Config {
.takes_value(true),
)
.arg(
Arg::with_name("asset_db_path")
.long("asset-db-path")
.help("Directory for liquid/elements asset db")
Arg::with_name("asset_registry_url")
.long("asset-registry-url")
.help("Base URL for the Liquid asset registry v2 service")
.takes_value(true),
);

Expand Down Expand Up @@ -369,7 +371,14 @@ impl Config {
});

#[cfg(feature = "liquid")]
let asset_db_path = m.value_of("asset_db_path").map(PathBuf::from);
let asset_registry_url = m.value_of("asset_registry_url").map(|value| {
let url = Url::parse(value).expect("invalid asset registry URL");
assert!(
matches!(url.scheme(), "http" | "https"),
"asset registry URL must use http or https"
);
url
});

let default_daemon_port = match network_type {
#[cfg(not(feature = "liquid"))]
Expand Down Expand Up @@ -572,7 +581,7 @@ impl Config {
#[cfg(feature = "liquid")]
parent_network,
#[cfg(feature = "liquid")]
asset_db_path,
asset_registry_url,

#[cfg(feature = "electrum-discovery")]
electrum_public_hosts,
Expand Down
9 changes: 2 additions & 7 deletions src/elements/asset.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};

use bitcoin::hashes::{sha256, Hash};
use elements::confidential::{Asset, Value};
Expand All @@ -9,7 +8,7 @@ use elements::{issuance::ContractHash, AssetId, AssetIssuance, OutPoint, Transac

use crate::chain::{BNetwork, BlockHash, Network, Txid};
use crate::elements::peg::{get_pegin_data, get_pegout_data, PeginInfo, PegoutInfo};
use crate::elements::registry::{AssetMeta, AssetRegistry};
use crate::elements::registry::AssetMeta;
use crate::errors::*;
use crate::new_index::schema::{TxHistoryInfo, TxHistoryKey, TxHistoryRow};
use crate::new_index::{db::DBFlush, ChainQuery, DBRow, Mempool, Query};
Expand Down Expand Up @@ -351,9 +350,8 @@ fn asset_history_row(

pub fn lookup_asset(
query: &Query,
registry: Option<&Arc<RwLock<AssetRegistry>>>,
asset_id: &AssetId,
meta: Option<&AssetMeta>, // may optionally be provided if already known
meta: Option<AssetMeta>,
) -> Result<Option<LiquidAsset>> {
if query.network().pegged_asset() == Some(asset_id) {
let (chain_stats, mempool_stats) = pegged_asset_stats(query, asset_id);
Expand All @@ -380,9 +378,6 @@ pub fn lookup_asset(
Ok(if let Some(row) = row {
let reissuance_token = parse_asset_id(&row.reissuance_token);

let meta = meta
.cloned()
.or_else(|| registry.and_then(|r| r.read().unwrap().get(asset_id).cloned()));
let stats = issued_asset_stats(query.chain(), &mempool, asset_id, &reissuance_token);
let status = query.get_tx_status(&deserialize(&row.issuance_txid).unwrap());

Expand Down
5 changes: 4 additions & 1 deletion src/elements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ mod registry;

use asset::get_issuance_entropy;
pub use asset::{lookup_asset, LiquidAsset};
pub use registry::{AssetRegistry, AssetSorting};
pub use registry::{
AssetMeta, AssetSearchFilters, AssetSorting, RegistryAsset, RegistryAssetList, RegistryClient,
RegistryContract, RegistryError, RegistryIcon,
};

#[derive(Serialize, Deserialize, Clone)]
pub struct IssuanceValue {
Expand Down
Loading
Loading