Skip to content

Commit 3c2b00c

Browse files
author
Ludo Galabru
committed
feat: polish first impression
1 parent 74ae98c commit 3c2b00c

File tree

6 files changed

+79
-106
lines changed

6 files changed

+79
-106
lines changed

Cargo.lock

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/hord-cli/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ rusqlite = { version = "0.27.0", features = ["bundled"] }
3939
anyhow = { version = "1.0.56", features = ["backtrace"] }
4040
schemars = { version = "0.8.10", git = "https://github.com/hirosystems/schemars.git", branch = "feat-chainhook-fixes" }
4141
pprof = { version = "0.12", features = ["flamegraph"], optional = true }
42+
progressing = '3'
4243

4344
[dependencies.rocksdb]
4445
version = "0.20.1"

components/hord-cli/src/archive/mod.rs

+48-25
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use crate::config::Config;
2-
use crate::utils::{read_file_content_at_path, write_file_content_at_path};
2+
use crate::utils::read_file_content_at_path;
33
use chainhook_sdk::types::BitcoinNetwork;
44
use chainhook_sdk::utils::Context;
55
use flate2::read::GzDecoder;
66
use futures_util::StreamExt;
77
use std::fs;
88
use std::io::{self, Cursor};
99
use std::io::{Read, Write};
10+
use progressing::Baring;
11+
use progressing::mapping::Bar as MappingBar;
1012

1113
pub fn default_sqlite_file_path(_network: &BitcoinNetwork) -> String {
1214
format!("hord.sqlite").to_lowercase()
@@ -16,28 +18,28 @@ pub fn default_sqlite_sha_file_path(_network: &BitcoinNetwork) -> String {
1618
format!("hord.sqlite.sha256").to_lowercase()
1719
}
1820

19-
pub async fn download_sqlite_file(config: &Config) -> Result<(), String> {
21+
pub async fn download_sqlite_file(config: &Config, ctx: &Context) -> Result<(), String> {
2022
let mut destination_path = config.expected_cache_path();
2123
std::fs::create_dir_all(&destination_path).unwrap_or_else(|e| {
2224
println!("{}", e.to_string());
2325
});
2426

25-
let remote_sha_url = config.expected_remote_ordinals_sqlite_sha256();
26-
let res = reqwest::get(&remote_sha_url)
27-
.await
28-
.or(Err(format!("Failed to GET from '{}'", &remote_sha_url)))?
29-
.bytes()
30-
.await
31-
.or(Err(format!("Failed to GET from '{}'", &remote_sha_url)))?;
32-
33-
let mut local_sha_file_path = destination_path.clone();
34-
local_sha_file_path.push(default_sqlite_sha_file_path(
35-
&config.network.bitcoin_network,
36-
));
27+
// let remote_sha_url = config.expected_remote_ordinals_sqlite_sha256();
28+
// let res = reqwest::get(&remote_sha_url)
29+
// .await
30+
// .or(Err(format!("Failed to GET from '{}'", &remote_sha_url)))?
31+
// .bytes()
32+
// .await
33+
// .or(Err(format!("Failed to GET from '{}'", &remote_sha_url)))?;
3734

38-
write_file_content_at_path(&local_sha_file_path, &res.to_vec())?;
35+
// let mut local_sha_file_path = destination_path.clone();
36+
// local_sha_file_path.push(default_sqlite_sha_file_path(
37+
// &config.network.bitcoin_network,
38+
// ));
39+
// write_file_content_at_path(&local_sha_file_path, &res.to_vec())?;
3940

4041
let file_url = config.expected_remote_ordinals_sqlite_url();
42+
println!("=> {file_url}");
4143
let res = reqwest::get(&file_url)
4244
.await
4345
.or(Err(format!("Failed to GET from '{}'", &file_url)))?;
@@ -59,9 +61,25 @@ pub async fn download_sqlite_file(config: &Config) -> Result<(), String> {
5961
});
6062

6163
if res.status() == reqwest::StatusCode::OK {
64+
let mut progress_bar = MappingBar::with_range(0i64, 4_800_001_704);
65+
progress_bar.set_len(40);
66+
info!(
67+
ctx.expect_logger(),
68+
"{}", progress_bar
69+
);
6270
let mut stream = res.bytes_stream();
71+
let mut progress = 0;
6372
while let Some(item) = stream.next().await {
6473
let chunk = item.or(Err(format!("Error while downloading file")))?;
74+
progress += chunk.len() as i64;
75+
progress_bar.set(progress);
76+
if progress_bar.has_progressed_significantly() {
77+
progress_bar.remember_significant_progress();
78+
info!(
79+
ctx.expect_logger(),
80+
"{}", progress_bar
81+
);
82+
}
6583
tx.send_async(chunk.to_vec())
6684
.await
6785
.map_err(|e| format!("unable to download stacks event: {}", e.to_string()))?;
@@ -116,14 +134,14 @@ pub async fn download_ordinals_dataset_if_required(config: &Config, ctx: &Contex
116134
let url = config.expected_remote_ordinals_sqlite_url();
117135
let mut sqlite_file_path = config.expected_cache_path();
118136
sqlite_file_path.push(default_sqlite_file_path(&config.network.bitcoin_network));
119-
let mut tsv_sha_file_path = config.expected_cache_path();
120-
tsv_sha_file_path.push(default_sqlite_sha_file_path(
137+
let mut sqlite_sha_file_path = config.expected_cache_path();
138+
sqlite_sha_file_path.push(default_sqlite_sha_file_path(
121139
&config.network.bitcoin_network,
122140
));
123141

124142
// Download archive if not already present in cache
125143
// Load the local
126-
let local_sha_file = read_file_content_at_path(&tsv_sha_file_path);
144+
let local_sha_file = read_file_content_at_path(&sqlite_sha_file_path);
127145
let sha_url = config.expected_remote_ordinals_sqlite_sha256();
128146

129147
let remote_sha_file = match reqwest::get(&sha_url).await {
@@ -136,22 +154,27 @@ pub async fn download_ordinals_dataset_if_required(config: &Config, ctx: &Contex
136154
if cache_not_expired {
137155
info!(
138156
ctx.expect_logger(),
139-
"More recent Stacks archive file detected"
157+
"More recent hord.sqlite file detected"
140158
);
141159
}
142160
cache_not_expired == false
143161
}
144162
(_, _) => {
145-
info!(
146-
ctx.expect_logger(),
147-
"Unable to retrieve Stacks archive file locally"
148-
);
149-
true
163+
match std::fs::metadata(&sqlite_file_path) {
164+
Ok(_) => false,
165+
_ => {
166+
info!(
167+
ctx.expect_logger(),
168+
"Unable to retrieve hord.sqlite file locally"
169+
);
170+
true
171+
}
172+
}
150173
}
151174
};
152175
if should_download {
153176
info!(ctx.expect_logger(), "Downloading {}", url);
154-
match download_sqlite_file(&config).await {
177+
match download_sqlite_file(&config, &ctx).await {
155178
Ok(_) => {}
156179
Err(e) => {
157180
error!(ctx.expect_logger(), "{}", e);

components/hord-cli/src/cli/mod.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::archive::download_ordinals_dataset_if_required;
12
use crate::config::generator::generate_config;
23
use crate::config::Config;
34
use crate::scan::bitcoin::scan_bitcoin_chainstate_via_rpc_using_predicate;
@@ -455,9 +456,13 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
455456
.get_sorted_entries();
456457

457458
if let Some(ref post_to) = cmd.post_to {
459+
info!(ctx.expect_logger(), "A fully synchronized bitcoind node is required for retrieving inscriptions content.");
460+
info!(ctx.expect_logger(), "Checking {}...", config.network.bitcoind_rpc_url);
458461
let tip = check_bitcoind_connection(&config).await?;
459462
if tip < cmd.end_block {
460-
error!(ctx.expect_logger(), "unable to scan block range [{}, {}]: underlying bitcoind synchronized until block {} ", cmd.start_block, cmd.end_block, tip);
463+
error!(ctx.expect_logger(), "Unable to scan block range [{}, {}]: underlying bitcoind synchronized until block {} ", cmd.start_block, cmd.end_block, tip);
464+
} else {
465+
info!(ctx.expect_logger(), "Starting scan");
461466
}
462467

463468
let predicate_spec = build_predicate_from_cli(
@@ -470,6 +475,8 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
470475
scan_bitcoin_chainstate_via_rpc_using_predicate(&predicate_spec, &config, &ctx)
471476
.await?;
472477
} else {
478+
let _ = download_ordinals_dataset_if_required(&config, ctx).await;
479+
473480
let inscriptions_db_conn =
474481
open_readonly_hord_db_conn(&config.expected_cache_path(), &ctx)?;
475482
while let Some(block_height) = block_range.pop_front() {
@@ -501,12 +508,13 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
501508
);
502509
}
503510
}
504-
println!(
505-
"Inscriptions revealed: {}, inscriptions transferred: {total_transfers}",
506-
inscriptions.len()
507-
);
508-
509-
println!("-----");
511+
if total_transfers > 0 && inscriptions.len() > 0 {
512+
println!(
513+
"Inscriptions revealed: {}, inscriptions transferred: {total_transfers}",
514+
inscriptions.len()
515+
);
516+
println!("-----");
517+
}
510518
}
511519
}
512520
}

components/hord-cli/src/config/mod.rs

+5-73
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@ use std::fs::File;
1212
use std::io::{BufReader, Read};
1313
use std::path::PathBuf;
1414

15-
const DEFAULT_MAINNET_STACKS_TSV_ARCHIVE: &str =
16-
"https://archive.hiro.so/mainnet/stacks-blockchain-api/mainnet-stacks-blockchain-api-latest";
17-
const DEFAULT_TESTNET_STACKS_TSV_ARCHIVE: &str =
18-
"https://archive.hiro.so/testnet/stacks-blockchain-api/testnet-stacks-blockchain-api-latest";
1915
const DEFAULT_MAINNET_ORDINALS_SQLITE_ARCHIVE: &str =
20-
"https://archive.hiro.so/mainnet/chainhooks/hord-latest.sqlite";
16+
"https://archive.hiro.so/mainnet/chainhooks/hord.sqlite";
2117
const DEFAULT_REDIS_URI: &str = "redis://localhost:6379/";
2218

2319
pub const DEFAULT_INGESTION_PORT: u16 = 20455;
@@ -56,8 +52,6 @@ pub struct PredicatesApiConfig {
5652

5753
#[derive(Clone, Debug)]
5854
pub enum EventSourceConfig {
59-
StacksTsvPath(PathConfig),
60-
StacksTsvUrl(UrlConfig),
6155
OrdinalsSqlitePath(PathConfig),
6256
OrdinalsSqliteUrl(UrlConfig),
6357
}
@@ -154,11 +148,11 @@ impl Config {
154148
if let Some(dst) = source.tsv_file_path.take() {
155149
let mut file_path = PathBuf::new();
156150
file_path.push(dst);
157-
event_sources.push(EventSourceConfig::StacksTsvPath(PathConfig { file_path }));
151+
event_sources.push(EventSourceConfig::OrdinalsSqlitePath(PathConfig { file_path }));
158152
continue;
159153
}
160154
if let Some(file_url) = source.tsv_file_url.take() {
161-
event_sources.push(EventSourceConfig::StacksTsvUrl(UrlConfig { file_url }));
155+
event_sources.push(EventSourceConfig::OrdinalsSqliteUrl(UrlConfig { file_url }));
162156
continue;
163157
}
164158
}
@@ -234,22 +228,14 @@ impl Config {
234228
pub fn is_initial_ingestion_required(&self) -> bool {
235229
for source in self.event_sources.iter() {
236230
match source {
237-
EventSourceConfig::StacksTsvUrl(_) | EventSourceConfig::StacksTsvPath(_) => {
231+
EventSourceConfig::OrdinalsSqlitePath(_) | EventSourceConfig::OrdinalsSqliteUrl(_) => {
238232
return true
239233
}
240-
_ => {}
241234
}
242235
}
243236
return false;
244237
}
245238

246-
pub fn add_local_stacks_tsv_source(&mut self, file_path: &PathBuf) {
247-
self.event_sources
248-
.push(EventSourceConfig::StacksTsvPath(PathConfig {
249-
file_path: file_path.clone(),
250-
}));
251-
}
252-
253239
pub fn add_ordinals_sqlite_remote_source_url(&mut self, file_url: &str) {
254240
self.event_sources
255241
.push(EventSourceConfig::OrdinalsSqliteUrl(UrlConfig {
@@ -275,15 +261,6 @@ impl Config {
275261
}
276262
}
277263

278-
pub fn expected_local_stacks_tsv_file(&self) -> &PathBuf {
279-
for source in self.event_sources.iter() {
280-
if let EventSourceConfig::StacksTsvPath(config) = source {
281-
return &config.file_path;
282-
}
283-
}
284-
panic!("expected local-tsv source")
285-
}
286-
287264
pub fn expected_cache_path(&self) -> PathBuf {
288265
let mut destination_path = PathBuf::new();
289266
destination_path.push(&self.storage.working_dir);
@@ -299,23 +276,6 @@ impl Config {
299276
panic!("expected remote-tsv source")
300277
}
301278

302-
fn expected_remote_stacks_tsv_base_url(&self) -> &String {
303-
for source in self.event_sources.iter() {
304-
if let EventSourceConfig::StacksTsvUrl(config) = source {
305-
return &config.file_url;
306-
}
307-
}
308-
panic!("expected remote-tsv source")
309-
}
310-
311-
pub fn expected_remote_stacks_tsv_sha256(&self) -> String {
312-
format!("{}.sha256", self.expected_remote_stacks_tsv_base_url())
313-
}
314-
315-
pub fn expected_remote_stacks_tsv_url(&self) -> String {
316-
format!("{}.gz", self.expected_remote_stacks_tsv_base_url())
317-
}
318-
319279
pub fn expected_remote_ordinals_sqlite_sha256(&self) -> String {
320280
format!("{}.sha256", self.expected_remote_ordinals_sqlite_base_url())
321281
}
@@ -324,15 +284,6 @@ impl Config {
324284
format!("{}.gz", self.expected_remote_ordinals_sqlite_base_url())
325285
}
326286

327-
pub fn rely_on_remote_stacks_tsv(&self) -> bool {
328-
for source in self.event_sources.iter() {
329-
if let EventSourceConfig::StacksTsvUrl(_config) = source {
330-
return true;
331-
}
332-
}
333-
false
334-
}
335-
336287
pub fn rely_on_remote_ordinals_sqlite(&self) -> bool {
337288
for source in self.event_sources.iter() {
338289
if let EventSourceConfig::OrdinalsSqliteUrl(_config) = source {
@@ -342,20 +293,6 @@ impl Config {
342293
false
343294
}
344295

345-
pub fn should_download_remote_stacks_tsv(&self) -> bool {
346-
let mut rely_on_remote_tsv = false;
347-
let mut remote_tsv_present_locally = false;
348-
for source in self.event_sources.iter() {
349-
if let EventSourceConfig::StacksTsvUrl(_config) = source {
350-
rely_on_remote_tsv = true;
351-
}
352-
if let EventSourceConfig::StacksTsvPath(_config) = source {
353-
remote_tsv_present_locally = true;
354-
}
355-
}
356-
rely_on_remote_tsv == true && remote_tsv_present_locally == false
357-
}
358-
359296
pub fn should_download_remote_ordinals_sqlite(&self) -> bool {
360297
let mut rely_on_remote_tsv = false;
361298
let mut remote_tsv_present_locally = false;
@@ -421,9 +358,7 @@ impl Config {
421358
working_dir: default_cache_path(),
422359
},
423360
http_api: PredicatesApi::Off,
424-
event_sources: vec![EventSourceConfig::StacksTsvUrl(UrlConfig {
425-
file_url: DEFAULT_TESTNET_STACKS_TSV_ARCHIVE.into(),
426-
})],
361+
event_sources: vec![],
427362
limits: LimitsConfig {
428363
max_number_of_bitcoin_predicates: BITCOIN_MAX_PREDICATE_REGISTRATION,
429364
max_number_of_concurrent_bitcoin_scans: BITCOIN_SCAN_THREAD_POOL_SIZE,
@@ -453,9 +388,6 @@ impl Config {
453388
},
454389
http_api: PredicatesApi::Off,
455390
event_sources: vec![
456-
EventSourceConfig::StacksTsvUrl(UrlConfig {
457-
file_url: DEFAULT_MAINNET_STACKS_TSV_ARCHIVE.into(),
458-
}),
459391
EventSourceConfig::OrdinalsSqliteUrl(UrlConfig {
460392
file_url: DEFAULT_MAINNET_ORDINALS_SQLITE_ARCHIVE.into(),
461393
}),

components/hord-cli/src/db/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
22
collections::{BTreeMap, HashMap},
3-
fs::File,
43
hash::BuildHasherDefault,
54
path::PathBuf,
65
sync::{mpsc::Sender, Arc},

0 commit comments

Comments
 (0)