Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement additional JSON endpoints (/inscription, /inscriptions) and bugfixes on /sat #2323

Merged
merged 14 commits into from
Aug 14, 2023
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ html-escaper = "0.2.0"
http = "0.2.6"
hyper = { version = "0.14.24", features = ["http1", "client"] }
indicatif = "0.17.1"
itertools = "0.11.0"
lazy_static = "1.4.0"
log = "0.4.14"
mime = "0.3.16"
Expand Down
2 changes: 1 addition & 1 deletion src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {super::*, clap::ValueEnum};

#[derive(Default, ValueEnum, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum Chain {
pub enum Chain {
#[default]
#[clap(alias("main"))]
Mainnet,
Expand Down
63 changes: 49 additions & 14 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use {
bitcoincore_rpc::{json::GetBlockHeaderResult, Client},
chrono::SubsecRound,
indicatif::{ProgressBar, ProgressStyle},
itertools::Itertools,
log::log_enabled,
redb::{
Database, MultimapTable, MultimapTableDefinition, ReadableMultimapTable, ReadableTable, Table,
Expand Down Expand Up @@ -57,7 +58,7 @@ define_table! { STATISTIC_TO_COUNT, u64, u64 }
define_table! { WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP, u64, u128 }

#[derive(Debug, PartialEq)]
pub(crate) enum List {
pub enum List {
Spent,
Unspent(Vec<(u64, u64)>),
}
Expand Down Expand Up @@ -877,19 +878,23 @@ impl Index {
&self,
n: usize,
from: Option<i64>,
) -> Result<(Vec<InscriptionId>, Option<i64>, Option<i64>)> {
) -> Result<(Vec<InscriptionId>, Option<i64>, Option<i64>, i64, i64)> {
let rtx = self.database.begin_read()?;

let inscription_number_to_inscription_id =
rtx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?;

let latest = match inscription_number_to_inscription_id.iter()?.next_back() {
let highest = match inscription_number_to_inscription_id.iter()?.next_back() {
Some(Ok((number, _id))) => number.value(),
Some(Err(_)) => return Ok(Default::default()),
None => return Ok(Default::default()),
Some(Err(_)) | None => return Ok(Default::default()),
};

let from = from.unwrap_or(latest);
let lowest = match inscription_number_to_inscription_id.iter()?.next() {
Some(Ok((number, _id))) => number.value(),
Some(Err(_)) | None => return Ok(Default::default()),
};

let from = from.unwrap_or(highest);

let prev = if let Some(prev) = from.checked_sub(n.try_into()?) {
inscription_number_to_inscription_id
Expand All @@ -899,12 +904,12 @@ impl Index {
None
};

let next = if from < latest {
let next = if from < highest {
Some(
from
.checked_add(n.try_into()?)
.unwrap_or(latest)
.min(latest),
.unwrap_or(highest)
.min(highest),
)
} else {
None
Expand All @@ -917,7 +922,35 @@ impl Index {
.flat_map(|result| result.map(|(_number, id)| Entry::load(*id.value())))
.collect();

Ok((inscriptions, prev, next))
Ok((inscriptions, prev, next, lowest, highest))
}

pub(crate) fn get_inscriptions_from_block(
&self,
block_height: u64,
) -> Result<Vec<InscriptionId>> {
// This is a naive approach and will require optimization, but we don't have an index by block
let block_inscriptions = self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)?
.iter()?
.filter_map(|result| match result {
Ok((key, entry_value)) => {
let entry = InscriptionEntry::load(entry_value.value());
if entry.height == block_height {
Some((InscriptionId::load(*key.value()), entry.number))
} else {
None
}
}
Err(_) => None,
})
.sorted_by_key(|&(_id, number)| number)
.map(|(id, _)| id)
.collect();

Ok(block_inscriptions)
}

pub(crate) fn get_feed_inscriptions(&self, n: usize) -> Result<Vec<(i64, InscriptionId)>> {
Expand Down Expand Up @@ -2447,7 +2480,7 @@ mod tests {

context.mine_blocks(1);

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _, _) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, None)
.unwrap();
Expand Down Expand Up @@ -2476,23 +2509,25 @@ mod tests {

ids.reverse();

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, lowest, highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, None)
.unwrap();
assert_eq!(inscriptions, &ids[..100]);
assert_eq!(prev, Some(2));
assert_eq!(next, None);
assert_eq!(highest, 102);
assert_eq!(lowest, 0);

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _lowest, _highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, Some(101))
.unwrap();
assert_eq!(inscriptions, &ids[1..101]);
assert_eq!(prev, Some(1));
assert_eq!(next, Some(102));

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _lowest, _highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, Some(0))
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) enum Curse {
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Inscription {
pub struct Inscription {
body: Option<Vec<u8>>,
content_type: Option<Vec<u8>>,
}
Expand Down
4 changes: 2 additions & 2 deletions src/inscription_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::*;

#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
pub struct InscriptionId {
pub(crate) txid: Txid,
pub(crate) index: u32,
pub txid: Txid,
pub index: u32,
}

impl<'de> Deserialize<'de> for InscriptionId {
Expand Down
Loading