From bfd62cdc607cd32b3bcd40a4bfd6ceabe760144b Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sat, 14 Oct 2023 15:22:39 -0700 Subject: [PATCH] Refactor index checks --- src/index.rs | 238 +++++++++++++++++++-------------------- src/index/testing.rs | 5 - src/index/updater.rs | 10 +- src/page_config.rs | 1 + src/runes.rs | 136 ++++++++++++---------- src/subcommand.rs | 15 ++- src/subcommand/find.rs | 4 + src/subcommand/list.rs | 4 + src/subcommand/server.rs | 62 ++++------ src/templates.rs | 69 +++++------- templates/page.html | 2 +- 11 files changed, 261 insertions(+), 285 deletions(-) diff --git a/src/index.rs b/src/index.rs index 4d7d96ad5c..2b64449f5e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -35,7 +35,7 @@ mod updater; #[cfg(test)] pub(crate) mod testing; -const SCHEMA_VERSION: u64 = 8; +const SCHEMA_VERSION: u64 = 9; macro_rules! define_table { ($name:ident, $key:ty, $value:ty) => { @@ -75,16 +75,17 @@ pub enum List { } #[derive(Copy, Clone)] -#[repr(u64)] pub(crate) enum Statistic { - Schema = 0, - Commits = 1, - LostSats = 2, - OutputsTraversed = 3, - SatRanges = 4, - UnboundInscriptions = 5, - CursedInscriptions = 6, - BlessedInscriptions = 7, + BlessedInscriptions, + Commits, + CursedInscriptions, + IndexRunes, + IndexSats, + LostSats, + OutputsTraversed, + SatRanges, + Schema, + UnboundInscriptions, } impl Statistic { @@ -154,6 +155,8 @@ pub(crate) struct Index { genesis_block_coinbase_transaction: Transaction, genesis_block_coinbase_txid: Txid, height_limit: Option, + index_runes: bool, + index_sats: bool, options: Options, path: PathBuf, unrecoverably_reorged: AtomicBool, @@ -207,19 +210,23 @@ impl Index { redb::Durability::Immediate }; + let index_runes; + let index_sats; + let database = match Database::builder() .set_cache_size(db_cache_size) .open(&path) { Ok(database) => { - let schema_version = database - .begin_read()? - .open_table(STATISTIC_TO_COUNT)? - .get(&Statistic::Schema.key())? - .map(|x| x.value()) - .unwrap_or(0); - - match schema_version.cmp(&SCHEMA_VERSION) { + { + let tx = database.begin_read()?; + let schema_version = tx + .open_table(STATISTIC_TO_COUNT)? + .get(&Statistic::Schema.key())? + .map(|x| x.value()) + .unwrap_or(0); + + match schema_version.cmp(&SCHEMA_VERSION) { cmp::Ordering::Less => bail!( "index at `{}` appears to have been built with an older, incompatible version of ord, consider deleting and rebuilding the index: index schema {schema_version}, ord schema {SCHEMA_VERSION}", @@ -234,6 +241,20 @@ impl Index { } } + let statistics = tx.open_table(STATISTIC_TO_COUNT)?; + + index_runes = statistics + .get(&Statistic::IndexRunes.key())? + .unwrap() + .value() + != 0; + index_sats = statistics + .get(&Statistic::IndexSats.key())? + .unwrap() + .value() + != 0; + } + database } Err(_) => { @@ -253,23 +274,28 @@ impl Index { tx.open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)?; tx.open_table(INSCRIPTION_ID_TO_SATPOINT)?; tx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?; + tx.open_table(OUTPOINT_TO_RUNE_BALANCES)?; tx.open_table(OUTPOINT_TO_VALUE)?; + tx.open_table(RUNE_ID_TO_RUNE_ENTRY)?; + tx.open_table(RUNE_TO_RUNE_ID)?; tx.open_table(SAT_TO_SATPOINT)?; tx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ID)?; tx.open_table(WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP)?; - tx.open_table(STATISTIC_TO_COUNT)? - .insert(&Statistic::Schema.key(), &SCHEMA_VERSION)?; + { + let mut outpoint_to_sat_ranges = tx.open_table(OUTPOINT_TO_SAT_RANGES)?; + let mut statistics = tx.open_table(STATISTIC_TO_COUNT)?; - if options.index_runes() { - tx.open_table(OUTPOINT_TO_RUNE_BALANCES)?; - tx.open_table(RUNE_ID_TO_RUNE_ENTRY)?; - tx.open_table(RUNE_TO_RUNE_ID)?; - } + outpoint_to_sat_ranges.insert(&OutPoint::null().store(), [].as_slice())?; + index_runes = options.index_runes(); + index_sats = options.index_sats; - if options.index_sats { - tx.open_table(OUTPOINT_TO_SAT_RANGES)? - .insert(&OutPoint::null().store(), [].as_slice())?; + statistics.insert( + &Statistic::IndexRunes.key(), + &u64::from(options.index_runes()), + )?; + statistics.insert(&Statistic::IndexSats.key(), &u64::from(options.index_sats))?; + statistics.insert(&Statistic::Schema.key(), &SCHEMA_VERSION)?; } tx.commit()?; @@ -290,6 +316,8 @@ impl Index { genesis_block_coinbase_transaction, height_limit: options.height_limit, options: options.clone(), + index_runes, + index_sats, path, unrecoverably_reorged: AtomicBool::new(false), }) @@ -358,28 +386,8 @@ impl Index { .collect() } - pub(crate) fn has_rune_index(&self) -> Result { - match self.begin_read()?.0.open_table(RUNE_ID_TO_RUNE_ENTRY) { - Ok(_) => Ok(true), - Err(redb::TableError::TableDoesNotExist(_)) => Ok(false), - Err(err) => Err(err.into()), - } - } - - pub(crate) fn has_sat_index(&self) -> Result { - match self.begin_read()?.0.open_table(OUTPOINT_TO_SAT_RANGES) { - Ok(_) => Ok(true), - Err(redb::TableError::TableDoesNotExist(_)) => Ok(false), - Err(err) => Err(err.into()), - } - } - - fn require_sat_index(&self, feature: &str) -> Result { - if !self.has_sat_index()? { - bail!("{feature} requires index created with `--index-sats` flag") - } - - Ok(()) + pub(crate) fn has_sat_index(&self) -> bool { + self.index_sats } pub(crate) fn info(&self) -> Result { @@ -602,76 +610,60 @@ impl Index { Ok(blocks) } - pub(crate) fn rare_sat_satpoints(&self) -> Result>> { - if self.has_sat_index()? { - let rtx = self.database.begin_read()?; - - let sat_to_satpoint = rtx.open_table(SAT_TO_SATPOINT)?; + pub(crate) fn rare_sat_satpoints(&self) -> Result> { + let rtx = self.database.begin_read()?; - let mut result = Vec::with_capacity(sat_to_satpoint.len()?.try_into().unwrap()); + let sat_to_satpoint = rtx.open_table(SAT_TO_SATPOINT)?; - for range in sat_to_satpoint.range(0..)? { - let (sat, satpoint) = range?; - result.push((Sat(sat.value()), Entry::load(*satpoint.value()))); - } + let mut result = Vec::with_capacity(sat_to_satpoint.len()?.try_into().unwrap()); - Ok(Some(result)) - } else { - Ok(None) + for range in sat_to_satpoint.range(0..)? { + let (sat, satpoint) = range?; + result.push((Sat(sat.value()), Entry::load(*satpoint.value()))); } + + Ok(result) } pub(crate) fn rare_sat_satpoint(&self, sat: Sat) -> Result> { - if self.has_sat_index()? { - Ok( - self - .database - .begin_read()? - .open_table(SAT_TO_SATPOINT)? - .get(&sat.n())? - .map(|satpoint| Entry::load(*satpoint.value())), - ) - } else { - Ok(None) - } + Ok( + self + .database + .begin_read()? + .open_table(SAT_TO_SATPOINT)? + .get(&sat.n())? + .map(|satpoint| Entry::load(*satpoint.value())), + ) } pub(crate) fn rune(&self, rune: Rune) -> Result> { - if self.has_rune_index()? { - let rtx = self.database.begin_read()?; - - let entry = match rtx.open_table(RUNE_TO_RUNE_ID)?.get(rune.0)? { - Some(id) => rtx - .open_table(RUNE_ID_TO_RUNE_ENTRY)? - .get(id.value())? - .map(|entry| (RuneId::load(id.value()), RuneEntry::load(entry.value()))), - None => None, - }; + let rtx = self.database.begin_read()?; - Ok(entry) - } else { - Ok(None) - } + let entry = match rtx.open_table(RUNE_TO_RUNE_ID)?.get(rune.0)? { + Some(id) => rtx + .open_table(RUNE_ID_TO_RUNE_ENTRY)? + .get(id.value())? + .map(|entry| (RuneId::load(id.value()), RuneEntry::load(entry.value()))), + None => None, + }; + + Ok(entry) } - pub(crate) fn runes(&self) -> Result>> { - if self.has_rune_index()? { - let mut entries = Vec::new(); + pub(crate) fn runes(&self) -> Result> { + let mut entries = Vec::new(); - for result in self - .database - .begin_read()? - .open_table(RUNE_ID_TO_RUNE_ENTRY)? - .iter()? - { - let (id, entry) = result?; - entries.push((RuneId::load(id.value()), RuneEntry::load(entry.value()))); - } - - Ok(Some(entries)) - } else { - Ok(None) + for result in self + .database + .begin_read()? + .open_table(RUNE_ID_TO_RUNE_ENTRY)? + .iter()? + { + let (id, entry) = result?; + entries.push((RuneId::load(id.value()), RuneEntry::load(entry.value()))); } + + Ok(entries) } #[cfg(test)] @@ -919,8 +911,6 @@ impl Index { } pub(crate) fn find(&self, sat: u64) -> Result> { - self.require_sat_index("find")?; - let rtx = self.begin_read()?; if rtx.block_count()? <= Sat(sat).height().n() { @@ -952,8 +942,6 @@ impl Index { range_start: u64, range_end: u64, ) -> Result>> { - self.require_sat_index("find")?; - let rtx = self.begin_read()?; if rtx.block_count()? < Sat(range_end - 1).height().n() + 1 { @@ -1012,7 +1000,9 @@ impl Index { } pub(crate) fn list(&self, outpoint: OutPoint) -> Result> { - self.require_sat_index("list")?; + if !self.index_sats { + return Ok(None); + } let array = outpoint.store(); @@ -1256,7 +1246,7 @@ impl Index { match sat { Some(sat) => { - if self.has_sat_index().unwrap() { + if self.index_sats { // unbound inscriptions should not be assigned to a sat assert!(satpoint.outpoint != unbound_outpoint()); assert!(rtx @@ -1284,7 +1274,7 @@ impl Index { } } None => { - if self.has_sat_index().unwrap() { + if self.index_sats { assert!(satpoint.outpoint == unbound_outpoint()) } } @@ -1333,19 +1323,17 @@ impl Index { } } - if self.has_sat_index().unwrap() { - for range in rtx - .open_multimap_table(SAT_TO_INSCRIPTION_ID) - .unwrap() - .iter() - .into_iter() - { - for entry in range.into_iter() { - let (_sat, ids) = entry.unwrap(); - assert!(!ids - .into_iter() - .any(|id| InscriptionId::load(*id.unwrap().value()) == inscription_id)) - } + for range in rtx + .open_multimap_table(SAT_TO_INSCRIPTION_ID) + .unwrap() + .iter() + .into_iter() + { + for entry in range.into_iter() { + let (_sat, ids) = entry.unwrap(); + assert!(!ids + .into_iter() + .any(|id| InscriptionId::load(*id.unwrap().value()) == inscription_id)) } } } diff --git a/src/index/testing.rs b/src/index/testing.rs index 1948cc2d3d..1dbf0f3b35 100644 --- a/src/index/testing.rs +++ b/src/index/testing.rs @@ -53,11 +53,6 @@ impl ContextBuilder { self } - pub(crate) fn chain(mut self, chain: Chain) -> Self { - self.chain = chain; - self - } - pub(crate) fn tempdir(mut self, tempdir: TempDir) -> Self { self.tempdir = Some(tempdir); self diff --git a/src/index/updater.rs b/src/index/updater.rs index 11fd03c8cc..03f5d51411 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -34,7 +34,6 @@ pub(crate) struct Updater<'index> { range_cache: HashMap>, height: u64, index: &'index Index, - index_sats: bool, sat_ranges_since_flush: u64, outputs_cached: u64, outputs_inserted_since_flush: u64, @@ -47,7 +46,6 @@ impl<'index> Updater<'_> { range_cache: HashMap::new(), height: index.block_count()?, index, - index_sats: index.has_sat_index()?, sat_ranges_since_flush: 0, outputs_cached: 0, outputs_inserted_since_flush: 0, @@ -84,7 +82,7 @@ impl<'index> Updater<'_> { Some(progress_bar) }; - let rx = Self::fetch_blocks_from(self.index, self.height, self.index_sats)?; + let rx = Self::fetch_blocks_from(self.index, self.height, self.index.index_sats)?; let (mut outpoint_sender, mut value_receiver) = Self::spawn_fetcher(self.index)?; @@ -378,7 +376,7 @@ impl<'index> Updater<'_> { } } - if index.options.index_runes() { + if index.index_runes { let mut outpoint_to_rune_balances = wtx.open_table(OUTPOINT_TO_RUNE_BALANCES)?; let mut rune_id_to_rune_entry = wtx.open_table(RUNE_ID_TO_RUNE_ENTRY)?; let mut rune_to_rune_id = wtx.open_table(RUNE_TO_RUNE_ID)?; @@ -446,7 +444,7 @@ impl<'index> Updater<'_> { value_cache, )?; - if self.index_sats { + if self.index.index_sats { let mut sat_to_satpoint = wtx.open_table(SAT_TO_SATPOINT)?; let mut outpoint_to_sat_ranges = wtx.open_table(OUTPOINT_TO_SAT_RANGES)?; @@ -668,7 +666,7 @@ impl<'index> Updater<'_> { self.outputs_cached ); - if self.index_sats { + if self.index.index_sats { log::info!( "Flushing {} entries ({:.1}% resulting from {} insertions) from memory to database", self.range_cache.len(), diff --git a/src/page_config.rs b/src/page_config.rs index c6510f2ca1..0bc36cb5cc 100644 --- a/src/page_config.rs +++ b/src/page_config.rs @@ -4,4 +4,5 @@ use super::*; pub(crate) struct PageConfig { pub(crate) chain: Chain, pub(crate) domain: Option, + pub(crate) index_sats: bool, } diff --git a/src/runes.rs b/src/runes.rs index 71de9b5e66..fc2d6adb23 100644 --- a/src/runes.rs +++ b/src/runes.rs @@ -23,30 +23,44 @@ mod tests { const RUNE: u128 = (21_000_000 * COIN_VALUE) as u128; - #[test] - fn index_only_indexes_runes_if_flag_is_passed_and_on_mainnet() { - assert!(!Context::builder().build().index.has_rune_index().unwrap()); - assert!(!Context::builder() - .arg("--index-runes-pre-alpha-i-agree-to-get-rekt") - .chain(Chain::Mainnet) - .build() - .index - .has_rune_index() - .unwrap()); - assert!(Context::builder() - .arg("--index-runes-pre-alpha-i-agree-to-get-rekt") - .build() - .index - .has_rune_index() - .unwrap()); - } - #[test] fn index_starts_with_no_runes() { let context = Context::builder() .arg("--index-runes-pre-alpha-i-agree-to-get-rekt") .build(); - assert_eq!(context.index.runes().unwrap().unwrap(), []); + assert_eq!(context.index.runes().unwrap(), []); + assert_eq!(context.index.rune_balances(), []); + } + + #[test] + fn default_index_does_not_index_runes() { + let context = Context::builder().build(); + + context.mine_blocks(1); + + context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, Witness::new())], + op_return: Some( + Runestone { + edicts: vec![Edict { + id: 0, + amount: u128::max_value(), + output: 0, + }], + etching: Some(Etching { + divisibility: 0, + rune: Rune(RUNE), + }), + } + .encipher(), + ), + ..Default::default() + }); + + context.mine_blocks(1); + + assert_eq!(context.index.runes().unwrap(), []); + assert_eq!(context.index.rune_balances(), []); } @@ -72,7 +86,7 @@ mod tests { context.mine_blocks(1); - assert_eq!(context.index.runes().unwrap().unwrap(), []); + assert_eq!(context.index.runes().unwrap(), []); assert_eq!(context.index.rune_balances(), []); } @@ -101,7 +115,7 @@ mod tests { context.mine_blocks(1); - assert_eq!(context.index.runes().unwrap().unwrap(), []); + assert_eq!(context.index.runes().unwrap(), []); assert_eq!(context.index.rune_balances(), []); } @@ -140,7 +154,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -190,7 +204,7 @@ mod tests { context.mine_blocks(1); - assert_eq!(context.index.runes().unwrap().unwrap(), []); + assert_eq!(context.index.runes().unwrap(), []); assert_eq!(context.index.rune_balances(), []); } @@ -229,7 +243,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -285,7 +299,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -347,7 +361,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -409,7 +423,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -464,7 +478,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -526,7 +540,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -591,7 +605,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -646,7 +660,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -690,7 +704,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -751,7 +765,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -791,7 +805,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -853,7 +867,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -887,7 +901,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -948,7 +962,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -989,7 +1003,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -1044,7 +1058,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id0, RuneEntry { @@ -1096,7 +1110,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1151,7 +1165,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1225,7 +1239,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id0, RuneEntry { @@ -1277,7 +1291,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1332,7 +1346,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1397,7 +1411,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1483,7 +1497,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id0, RuneEntry { @@ -1535,7 +1549,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1608,7 +1622,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1683,7 +1697,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -1722,7 +1736,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -1801,7 +1815,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -1884,7 +1898,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -1935,7 +1949,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -1996,7 +2010,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id0, RuneEntry { @@ -2048,7 +2062,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -2121,7 +2135,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [ ( id0, @@ -2204,7 +2218,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -2248,7 +2262,7 @@ mod tests { context.mine_blocks(1); assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -2309,7 +2323,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -2365,7 +2379,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { @@ -2428,7 +2442,7 @@ mod tests { }; assert_eq!( - context.index.runes().unwrap().unwrap(), + context.index.runes().unwrap(), [( id, RuneEntry { diff --git a/src/subcommand.rs b/src/subcommand.rs index a7a1159415..536962aeb3 100644 --- a/src/subcommand.rs +++ b/src/subcommand.rs @@ -14,14 +14,15 @@ pub mod supply; pub mod traits; pub mod wallet; +// todo: commands that should error if no sat index: +// - wallet sats + #[derive(Debug, Parser)] pub(crate) enum Subcommand { #[command(about = "Decode a transaction")] Decode(decode::Decode), #[command(about = "List the first satoshis of each reward epoch")] Epochs, - #[command(about = "Run an explorer server populated with inscriptions")] - Preview(preview::Preview), #[command(about = "Find a satoshi's current location")] Find(find::Find), #[command(subcommand, about = "Index commands")] @@ -32,10 +33,12 @@ pub(crate) enum Subcommand { List(list::List), #[command(about = "Parse a satoshi from ordinal notation")] Parse(parse::Parse), - #[command(about = "Display information about a block's subsidy")] - Subsidy(subsidy::Subsidy), + #[command(about = "Run an explorer server populated with inscriptions")] + Preview(preview::Preview), #[command(about = "Run the explorer server")] Server(server::Server), + #[command(about = "Display information about a block's subsidy")] + Subsidy(subsidy::Subsidy), #[command(about = "Display Bitcoin supply information")] Supply, #[command(about = "Display satoshi traits")] @@ -49,19 +52,19 @@ impl Subcommand { match self { Self::Decode(decode) => decode.run(), Self::Epochs => epochs::run(), - Self::Preview(preview) => preview.run(), Self::Find(find) => find.run(options), Self::Index(index) => index.run(options), Self::Info(info) => info.run(options), Self::List(list) => list.run(options), Self::Parse(parse) => parse.run(), - Self::Subsidy(subsidy) => subsidy.run(), + Self::Preview(preview) => preview.run(), Self::Server(server) => { let index = Arc::new(Index::open(&options)?); let handle = axum_server::Handle::new(); LISTENERS.lock().unwrap().push(handle.clone()); server.run(options, index, handle) } + Self::Subsidy(subsidy) => subsidy.run(), Self::Supply => supply::run(), Self::Traits(traits) => traits.run(), Self::Wallet(wallet) => wallet.run(options), diff --git a/src/subcommand/find.rs b/src/subcommand/find.rs index b52601a2c6..deb28c44f2 100644 --- a/src/subcommand/find.rs +++ b/src/subcommand/find.rs @@ -24,6 +24,10 @@ impl Find { pub(crate) fn run(self, options: Options) -> SubcommandResult { let index = Index::open(&options)?; + if !index.has_sat_index() { + bail!("find requires index created with `--index-sats` flag"); + } + index.update()?; match self.end { diff --git a/src/subcommand/list.rs b/src/subcommand/list.rs index e995522808..c0477407c0 100644 --- a/src/subcommand/list.rs +++ b/src/subcommand/list.rs @@ -21,6 +21,10 @@ impl List { pub(crate) fn run(self, options: Options) -> SubcommandResult { let index = Index::open(&options)?; + if !index.has_sat_index() { + bail!("list requires index created with `--index-sats` flag"); + } + index.update()?; match index.list(self.outpoint)? { diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 86b888c4a4..00109d6399 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -178,6 +178,7 @@ impl Server { let page_config = Arc::new(PageConfig { chain: options.chain(), domain: acme_domains.first().cloned(), + index_sats: index.has_sat_index(), }); let router = Router::new() @@ -465,7 +466,7 @@ impl Server { blocktime, inscriptions, } - .page(page_config, index.has_sat_index()?) + .page(page_config) .into_response() }) } @@ -480,11 +481,7 @@ impl Server { Path(outpoint): Path, accept_json: AcceptJson, ) -> ServerResult { - let list = if index.has_sat_index()? { - index.list(outpoint)? - } else { - None - }; + let list = index.list(outpoint)?; let output = if outpoint == OutPoint::null() || outpoint == unbound_outpoint() { let mut value = 0; @@ -528,14 +525,13 @@ impl Server { chain: page_config.chain, output, } - .page(page_config, index.has_sat_index()?) + .page(page_config) .into_response() }) } async fn range( Extension(page_config): Extension>, - Extension(index): Extension>, Path((DeserializeFromStr(start), DeserializeFromStr(end))): Path<( DeserializeFromStr, DeserializeFromStr, @@ -546,16 +542,12 @@ impl Server { Ordering::Greater => Err(ServerError::BadRequest( "range start greater than range end".to_string(), )), - Ordering::Less => Ok(RangeHtml { start, end }.page(page_config, index.has_sat_index()?)), + Ordering::Less => Ok(RangeHtml { start, end }.page(page_config)), } } async fn rare_txt(Extension(index): Extension>) -> ServerResult { - Ok(RareTxt(index.rare_sat_satpoints()?.ok_or_else(|| { - ServerError::NotFound( - "tracking rare sats requires index created with `--index-sats` flag".into(), - ) - })?)) + Ok(RareTxt(index.rare_sat_satpoints()?)) } async fn rune( @@ -584,7 +576,7 @@ impl Server { entry, inscription, } - .page(page_config, index.has_sat_index()?), + .page(page_config), ) } @@ -592,13 +584,12 @@ impl Server { Extension(page_config): Extension>, Extension(index): Extension>, ) -> ServerResult> { - let entries = index.runes()?.ok_or_else(|| { - ServerError::NotFound( - "tracking runes requires index created with `--index-runes-pre-alpha-i-agree-to-get-rekt` flag".into(), - ) - })?; - - Ok(RunesHtml { entries }.page(page_config, index.has_sat_index()?)) + Ok( + RunesHtml { + entries: index.runes()?, + } + .page(page_config), + ) } async fn home( @@ -614,7 +605,7 @@ impl Server { featured_blocks.insert(*hash, inscriptions); } - Ok(HomeHtml::new(blocks, featured_blocks).page(page_config, index.has_sat_index()?)) + Ok(HomeHtml::new(blocks, featured_blocks).page(page_config)) } async fn install_script() -> Redirect { @@ -658,7 +649,7 @@ impl Server { total_num, featured_inscriptions, ) - .page(page_config, index.has_sat_index()?), + .page(page_config), ) } @@ -680,7 +671,7 @@ impl Server { inscription.map(|_| InscriptionId { txid, index: 0 }), page_config.chain, ) - .page(page_config, index.has_sat_index()?), + .page(page_config), ) } @@ -893,7 +884,7 @@ impl Server { .nth(path.2) .ok_or_not_found(not_found)?; - Ok(InputHtml { path, input }.page(page_config, index.has_sat_index()?)) + Ok(InputHtml { path, input }.page(page_config)) } async fn faq() -> Redirect { @@ -1121,7 +1112,7 @@ impl Server { satpoint, timestamp: timestamp(entry.timestamp), } - .page(page_config, index.has_sat_index()?) + .page(page_config) .into_response() }) } @@ -1166,7 +1157,7 @@ impl Server { inscriptions, page_index, )? - .page(page_config, index.has_sat_index()?) + .page(page_config) .into_response() }) } @@ -1213,7 +1204,7 @@ impl Server { next, prev, } - .page(page_config, index.has_sat_index()?) + .page(page_config) .into_response() }) } @@ -2266,15 +2257,6 @@ mod tests { ); } - #[test] - fn rare_without_sat_index() { - TestServer::new().assert_response( - "/rare.txt", - StatusCode::NOT_FOUND, - "tracking rare sats requires index created with `--index-sats` flag", - ); - } - #[test] fn show_rare_txt_in_header_with_sat_index() { TestServer::new_with_sat_index().assert_response_regex( @@ -3158,7 +3140,7 @@ mod tests { }; assert_eq!( - server.index.runes().unwrap().unwrap(), + server.index.runes().unwrap(), [( id, RuneEntry { @@ -3225,7 +3207,7 @@ mod tests { }; assert_eq!( - server.index.runes().unwrap().unwrap(), + server.index.runes().unwrap(), [( id, RuneEntry { diff --git a/src/templates.rs b/src/templates.rs index 993a884b6f..5b5f456136 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -45,24 +45,19 @@ mod transaction; #[derive(Boilerplate)] pub(crate) struct PageHtml { content: T, - has_sat_index: bool, - page_config: Arc, + config: Arc, } impl PageHtml where T: PageContent, { - pub(crate) fn new(content: T, page_config: Arc, has_sat_index: bool) -> Self { - Self { - content, - has_sat_index, - page_config, - } + pub(crate) fn new(content: T, config: Arc) -> Self { + Self { content, config } } fn og_image(&self) -> String { - if let Some(domain) = &self.page_config.domain { + if let Some(domain) = &self.config.domain { format!("https://{domain}/static/favicon.png") } else { "https://ordinals.com/static/favicon.png".into() @@ -70,10 +65,10 @@ where } fn superscript(&self) -> String { - if self.page_config.chain == Chain::Mainnet { + if self.config.chain == Chain::Mainnet { "alpha".into() } else { - self.page_config.chain.to_string() + self.config.chain.to_string() } } } @@ -81,11 +76,11 @@ where pub(crate) trait PageContent: Display + 'static { fn title(&self) -> String; - fn page(self, page_config: Arc, has_sat_index: bool) -> PageHtml + fn page(self, page_config: Arc) -> PageHtml where Self: Sized, { - PageHtml::new(self, page_config, has_sat_index) + PageHtml::new(self, page_config) } fn preview_image_url(&self) -> Option> { @@ -114,13 +109,11 @@ mod tests { #[test] fn page() { assert_regex_match!( - Foo.page( - Arc::new(PageConfig { - chain: Chain::Mainnet, - domain: Some("signet.ordinals.com".into()) - }), - true - ), + Foo.page(Arc::new(PageConfig { + chain: Chain::Mainnet, + domain: Some("signet.ordinals.com".into()), + index_sats: true, + }),), r" @@ -161,13 +154,11 @@ mod tests { #[test] fn page_mainnet() { assert_regex_match!( - Foo.page( - Arc::new(PageConfig { - chain: Chain::Mainnet, - domain: None - }), - true - ), + Foo.page(Arc::new(PageConfig { + chain: Chain::Mainnet, + domain: None, + index_sats: true, + }),), r".*