Skip to content

Commit

Permalink
work with offset=0 and vout=0
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph committed Nov 30, 2022
1 parent 307fcc6 commit f48c69c
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 46 deletions.
62 changes: 45 additions & 17 deletions src/index.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use {
self::updater::Updater,
super::*,
bitcoin::consensus::encode::deserialize,
bitcoin::BlockHeader,
bitcoincore_rpc::{json::GetBlockHeaderResult, Auth, Client},
indicatif::{ProgressBar, ProgressStyle},
Expand Down Expand Up @@ -33,6 +32,10 @@ const INSCRIPTION_ID_TO_INSCRIPTION: TableDefinition<&InscriptionIdArray, str> =
TableDefinition::new("INSCRIPTION_ID_TO_INSCRIPTION");
const WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP: TableDefinition<u64, u128> =
TableDefinition::new("WRITE_TRANSACTION_START_BLOCK_COUNT_TO_TIMESTAMP");
const INSCRIPTION_ID_TO_SATPOINT: TableDefinition<&InscriptionIdArray, &SatPointArray> =
TableDefinition::new("INSCRIPTION_ID_TO_SATPOINT");
const SATPOINT_TO_INSCRIPTION_ID: TableDefinition<&SatPointArray, &InscriptionIdArray> =
TableDefinition::new("SATPOINT_TO_INSCRIPTION_ID");

fn encode_outpoint(outpoint: OutPoint) -> OutPointArray {
let mut array = [0; 36];
Expand All @@ -50,6 +53,14 @@ fn encode_satpoint(satpoint: SatPoint) -> SatPointArray {
array
}

fn decode_satpoint(array: SatPointArray) -> SatPoint {
Decodable::consensus_decode(&mut io::Cursor::new(array)).unwrap()
}

fn decode_outpoint(array: OutPointArray) -> OutPoint {
Decodable::consensus_decode(&mut io::Cursor::new(array)).unwrap()
}

pub(crate) struct Index {
auth: Auth,
chain: Chain,
Expand Down Expand Up @@ -190,10 +201,12 @@ impl Index {
};

tx.open_table(HEIGHT_TO_BLOCK_HASH)?;
tx.open_table(INSCRIPTION_ID_TO_INSCRIPTION)?;
tx.open_table(INSCRIPTION_ID_TO_SATPOINT)?;
tx.open_table(ORDINAL_TO_INSCRIPTION_ID)?;
tx.open_table(ORDINAL_TO_SATPOINT)?;
tx.open_table(SATPOINT_TO_INSCRIPTION_ID)?;
tx.open_table(STATISTIC_TO_COUNT)?;
tx.open_table(INSCRIPTION_ID_TO_INSCRIPTION)?;
tx.open_table(WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP)?;

if options.index_ordinals {
Expand Down Expand Up @@ -384,7 +397,7 @@ impl Index {
let ordinal_to_satpoint = rtx.open_table(ORDINAL_TO_SATPOINT)?;

for (ordinal, satpoint) in ordinal_to_satpoint.range(0..)? {
result.push((Ordinal(ordinal), deserialize(satpoint)?));
result.push((Ordinal(ordinal), decode_satpoint(*satpoint)));
}

Ok(result)
Expand Down Expand Up @@ -413,7 +426,7 @@ impl Index {
self.client.get_block(&hash).into_option()
}

pub(crate) fn inscription(&self, ordinal: Ordinal) -> Result<Option<Inscription>> {
pub(crate) fn get_inscription_by_ordinal(&self, ordinal: Ordinal) -> Result<Option<Inscription>> {
let db = self.database.begin_read()?;
let table = db.open_table(ORDINAL_TO_INSCRIPTION_ID)?;

Expand All @@ -434,18 +447,33 @@ impl Index {
)
}

pub(crate) fn inscription_from_txid(&self, txid: Txid) -> Result<Option<Inscription>> {
Ok(
self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_INSCRIPTION)?
.get(txid.as_inner())?
.map(|inscription| {
serde_json::from_str(inscription)
.expect("failed to deserialize inscription (JSON) from database")
}),
)
pub(crate) fn get_inscription_by_inscription_id(
&self,
txid: Txid,
) -> Result<Option<(Inscription, SatPoint)>> {
let inscription = self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_INSCRIPTION)?
.get(txid.as_inner())?
.map(|inscription| {
serde_json::from_str(inscription)
.expect("failed to deserialize inscription (JSON) from database")
});

let inscription = match inscription {
Some(inscription) => inscription,
None => return Ok(None),
};

let satpoint = decode_satpoint(*self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_SATPOINT)?
.get(txid.as_inner())?
.ok_or_else(|| anyhow!("no satpoint for inscription"))?);

Ok(Some((inscription, satpoint)))
}

pub(crate) fn transaction(&self, txid: Txid) -> Result<Option<Transaction>> {
Expand Down Expand Up @@ -487,7 +515,7 @@ impl Index {
for chunk in value.chunks_exact(11) {
let (start, end) = Index::decode_ordinal_range(chunk.try_into().unwrap());
if start <= ordinal && ordinal < end {
let outpoint: OutPoint = deserialize(key.as_slice())?;
let outpoint = decode_outpoint(*key);
return Ok(Some(SatPoint {
outpoint,
offset: offset + ordinal - start,
Expand Down
65 changes: 48 additions & 17 deletions src/index/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,16 @@ impl Updater {
}
} else {
let mut inscription_id_to_inscription = wtx.open_table(INSCRIPTION_ID_TO_INSCRIPTION)?;
let mut inscription_id_to_satpoint = wtx.open_table(INSCRIPTION_ID_TO_SATPOINT)?;
let mut satpoint_to_inscription_id = wtx.open_table(SATPOINT_TO_INSCRIPTION_ID)?;

for tx in &block.txdata {
self.index_transaction_inscriptions(tx, &mut inscription_id_to_inscription)?
self.index_transaction_inscriptions(
tx,
&mut inscription_id_to_inscription,
&mut inscription_id_to_satpoint,
&mut satpoint_to_inscription_id,
)?
}
}

Expand All @@ -341,32 +348,56 @@ impl Updater {
&mut self,
tx: &Transaction,
inscription_id_to_inscription: &mut Table<&InscriptionIdArray, str>,
// inscription_id_to_satpoint: &mut Table<&[u8; 32], &[u8; 44]>,
satpoint_to_inscription_id: &mut Table<&[u8; 44], &[u8; 32]>,
inscription_id_to_satpoint: &mut Table<&InscriptionIdArray, &SatPointArray>,
satpoint_to_inscription_id: &mut Table<&SatPointArray, &InscriptionIdArray>,
) -> Result {
if let Some(inscription) = Inscription::from_transaction(tx) {
let json = serde_json::to_string(&inscription)
.expect("Inscription serialization should always succeed");

inscription_id_to_inscription.insert(tx.txid().as_inner(), &json)?;
let txid = tx.txid();
let satpoint = encode_satpoint(SatPoint {
outpoint: OutPoint { txid, vout: 0 },
offset: 0,
});

inscription_id_to_inscription.insert(txid.as_inner(), &json)?;
inscription_id_to_satpoint.insert(txid.as_inner(), &satpoint)?;
satpoint_to_inscription_id.insert(&satpoint, txid.as_inner())?;
}

for tx_in in tx.input {
let mut offset = 0;
let outpoint = tx_in.previous_output;
let start = encode_satpoint(SatPoint { outpoint, offset: 0 });
let end = encode_satpoint(SatPoint { outpoint, offset: u64::MAX });
if let inscription_ids = satpoint_to_inscription_id.range(start..=end)? {
for id in inscription_ids {
let new_satpoint = encode_satpoint(SatPoint { outpoint: OutPoint { txid: tx.txid(), vout: 0 }, offset: 0 });
satpoint_to_inscription_id.insert(&new_satpoint, &id.1) ;
}
} else {

for tx_in in &tx.input {
let outpoint = tx_in.previous_output;
let start = encode_satpoint(SatPoint {
outpoint,
offset: 0,
});

let end = encode_satpoint(SatPoint {
outpoint,
offset: u64::MAX,
});

let inscription_ids: Vec<(SatPointArray, InscriptionIdArray)> = satpoint_to_inscription_id
.range(start..=end)?
.map(|(satpoint, id)| (*satpoint, *id))
.collect();

for id in inscription_ids {
let new_satpoint = encode_satpoint(SatPoint {
outpoint: OutPoint {
txid: tx.txid(),
vout: 0,
},
offset: 0,
});

satpoint_to_inscription_id.insert(&new_satpoint, &id.1)?;
inscription_id_to_satpoint.insert(&id.1, &new_satpoint)?;
}
}
// check each input of tx for inscription outpoints -> index from satpoint to inscription_id
// record satpoint (txid:vout:offset) in same table
// record satpoint (txid:vout:offset) in same table

Ok(())
}
Expand Down
21 changes: 12 additions & 9 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl Server {
blocktime: index.blocktime(ordinal.height()).map_err(|err| {
ServerError::Internal(anyhow!("failed to retrieve blocktime from index: {err}"))
})?,
inscription: index.inscription(ordinal).map_err(|err| {
inscription: index.get_inscription_by_ordinal(ordinal).map_err(|err| {
ServerError::Internal(anyhow!(
"failed to retrieve inscription for ordinal {ordinal} from index: {err}"
))
Expand Down Expand Up @@ -613,17 +613,20 @@ impl Server {
Extension(index): Extension<Arc<Index>>,
Path(txid): Path<Txid>,
) -> ServerResult<PageHtml> {
let (inscription, satpoint) = index
.get_inscription_by_inscription_id(txid)
.map_err(|err| {
ServerError::Internal(anyhow!(
"failed to retrieve inscription from txid {txid} from index: {err}"
))
})?
.ok_or_else(|| ServerError::NotFound(format!("transaction {txid} has no inscription")))?;

Ok(
InscriptionHtml {
txid,
inscription: index
.inscription_from_txid(txid)
.map_err(|err| {
ServerError::Internal(anyhow!(
"failed to retrieve inscription from txid {txid} from index: {err}"
))
})?
.ok_or_else(|| ServerError::NotFound(format!("transaction {txid} has no inscription")))?,
inscription,
satpoint,
}
.page(
chain,
Expand Down
11 changes: 11 additions & 0 deletions src/subcommand/server/templates/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::*;
pub(crate) struct InscriptionHtml {
pub(crate) txid: Txid,
pub(crate) inscription: Inscription,
pub(crate) satpoint: SatPoint,
}

impl Content for InscriptionHtml {
Expand All @@ -23,10 +24,15 @@ mod tests {
txid: Txid::from_str("ec90757eb3b164aa43fc548faa2fa0c52025494f2c15d5ddf11260b4034ac6dc")
.unwrap(),
inscription: Inscription::Text("HELLOWORLD".into()),
satpoint: satpoint(1, 0),
}
.to_string(),
"
<h1>Inscription</h1>
<dl>
<dt>satpoint</dt>
<dd>1111111111111111111111111111111111111111111111111111111111111111:1:0</dd>
</dl>
HELLOWORLD
"
.unindent()
Expand All @@ -39,10 +45,15 @@ mod tests {
InscriptionHtml {
txid: Txid::from_str("ec90757eb3b164aa43fc548faa2fa0c52025494f2c15d5ddf11260b4034ac6dc").unwrap(),
inscription: Inscription::Png(vec![1; 100]),
satpoint: satpoint(1, 0),
}
.to_string(),
"
<h1>Inscription</h1>
<dl>
<dt>satpoint</dt>
<dd>1111111111111111111111111111111111111111111111111111111111111111:1:0</dd>
</dl>
<img src=\"data:image/png;base64,AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==\">
"
.unindent()
Expand Down
4 changes: 4 additions & 0 deletions templates/inscription.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<h1>Inscription</h1>
<dl>
<dt>satpoint</dt>
<dd>{{ self.satpoint }}</dd>
</dl>
%% match &self.inscription {
%% Inscription::Text(content) => {
{{ content }}
Expand Down
12 changes: 9 additions & 3 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,21 @@ fn inscription_page() {
.stdout_regex("commit\t[[:xdigit:]]{64}\nreveal\t[[:xdigit:]]{64}\n")
.run();

let reveal_tx = stdout.split("reveal\t").collect::<Vec<&str>>()[1];
let reveal_tx = stdout.split("reveal\t").collect::<Vec<&str>>()[1].trim();

rpc_server.mine_blocks(1);

let ord_server = TestServer::spawn_with_args(&rpc_server, &["--index-ordinals"]);
let ord_server = TestServer::spawn_with_args(&rpc_server, &[]);

ord_server.assert_response_regex(
&format!("/inscription/{}", reveal_tx),
".*<h1>Inscription</h1>
&format!(
".*<h1>Inscription</h1>
<dl>
<dt>satpoint</dt>
<dd>{reveal_tx}:0:0</dd>
</dl>
HELLOWORLD.*",
),
)
}

0 comments on commit f48c69c

Please sign in to comment.