Skip to content

Commit

Permalink
Only index ordinal ranges if --index-ordinals is passed (#837)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Nov 24, 2022
1 parent 4942812 commit 7e696ef
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 145 deletions.
3 changes: 2 additions & 1 deletion deploy/ord-dev.service
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Environment=RUST_BACKTRACE=1
Environment=RUST_LOG=info
ExecStart=/usr/local/bin/ord-dev \
--bitcoin-data-dir /var/lib/bitcoind \
--data-dir /var/lib/ord-dev \
--chain ${CHAIN} \
--data-dir /var/lib/ord-dev \
--index-ordinals \
server \
--http-port 8080
Group=ord
Expand Down
1 change: 1 addition & 0 deletions deploy/ord.service
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ExecStart=/usr/local/bin/ord \
--bitcoin-data-dir /var/lib/bitcoind \
--data-dir /var/lib/ord \
--chain ${CHAIN} \
--index-ordinals \
server \
--acme-contact mailto:casey@rodarmor.com \
--http \
Expand Down
63 changes: 41 additions & 22 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ mod updater;

const HEIGHT_TO_BLOCK_HASH: TableDefinition<u64, [u8; 32]> =
TableDefinition::new("HEIGHT_TO_BLOCK_HASH");
const WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP: TableDefinition<u64, u128> =
TableDefinition::new("WRITE_TRANSACTION_START_BLOCK_COUNT_TO_TIMESTAMP");
const ORDINAL_TO_INSCRIPTION_TXID: TableDefinition<u64, [u8; 32]> =
TableDefinition::new("ORDINAL_TO_INSCRIPTION_TXID");
const ORDINAL_TO_SATPOINT: TableDefinition<u64, [u8; 44]> =
Expand All @@ -27,6 +25,8 @@ const OUTPOINT_TO_ORDINAL_RANGES: TableDefinition<[u8; 36], [u8]> =
const STATISTIC_TO_COUNT: TableDefinition<u64, u64> = TableDefinition::new("STATISTIC_TO_COUNT");
const TXID_TO_INSCRIPTION: TableDefinition<[u8; 32], str> =
TableDefinition::new("TXID_TO_INSCRIPTION");
const WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP: TableDefinition<u64, u128> =
TableDefinition::new("WRITE_TRANSACTION_START_BLOCK_COUNT_TO_TIMESTAMP");

fn encode_outpoint(outpoint: OutPoint) -> [u8; 36] {
let mut array = [0; 36];
Expand All @@ -53,6 +53,7 @@ pub(crate) struct Index {
genesis_block_coinbase_transaction: Transaction,
genesis_block_coinbase_txid: Txid,
height_limit: Option<u64>,
index_ordinals: bool,
reorged: AtomicBool,
rpc_url: String,
}
Expand Down Expand Up @@ -198,11 +199,20 @@ impl Index {
database_path,
genesis_block_coinbase_transaction,
height_limit: options.height_limit,
index_ordinals: options.index_ordinals,
reorged: AtomicBool::new(false),
rpc_url,
})
}

fn require_ordinal_index(&self, feature: &str) -> Result {
if !self.index_ordinals {
bail!("{feature} requires `--index-ordinals` flag")
}

Ok(())
}

pub(crate) fn info(&self) -> Result<Info> {
let wtx = self.begin_write()?;

Expand Down Expand Up @@ -297,6 +307,13 @@ impl Index {

#[cfg(test)]
pub(crate) fn statistic(&self, statistic: Statistic) -> Result<u64> {
if matches!(
statistic,
Statistic::OutputsTraversed | Statistic::OrdinalRanges
) {
self.require_ordinal_index("statistic")?;
}

Ok(
self
.database
Expand Down Expand Up @@ -332,6 +349,8 @@ impl Index {
}

pub(crate) fn rare_ordinal_satpoints(&self) -> Result<Vec<(Ordinal, SatPoint)>> {
self.require_ordinal_index("looking up rare ordinals")?;

let mut result = Vec::new();

let rtx = self.database.begin_read()?;
Expand Down Expand Up @@ -427,6 +446,8 @@ impl Index {
}

pub(crate) fn find(&self, ordinal: u64) -> Result<Option<SatPoint>> {
self.require_ordinal_index("find")?;

let rtx = self.begin_read()?;

if rtx.block_count()? <= Ordinal(ordinal).height().n() {
Expand All @@ -453,7 +474,7 @@ impl Index {
Ok(None)
}

pub(crate) fn list_inner(&self, outpoint: &[u8]) -> Result<Option<Vec<u8>>> {
fn list_inner(&self, outpoint: &[u8]) -> Result<Option<Vec<u8>>> {
Ok(
self
.database
Expand All @@ -465,6 +486,8 @@ impl Index {
}

pub(crate) fn list(&self, outpoint: OutPoint) -> Result<Option<List>> {
self.require_ordinal_index("find")?;

let outpoint_encoded = encode_outpoint(outpoint);

let ordinal_ranges = self.list_inner(&outpoint_encoded)?;
Expand Down Expand Up @@ -526,10 +549,6 @@ mod tests {
}

impl Context {
fn new() -> Self {
Self::with_args("")
}

fn with_args(args: &str) -> Self {
let rpc_server = test_bitcoincore_rpc::spawn();

Expand Down Expand Up @@ -593,7 +612,7 @@ mod tests {

#[test]
fn list_first_coinbase_transaction() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
assert_eq!(
context
.index
Expand All @@ -610,7 +629,7 @@ mod tests {

#[test]
fn list_second_coinbase_transaction() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
let txid = context.rpc_server.mine_blocks(1)[0].txdata[0].txid();
context.index.update().unwrap();
assert_eq!(
Expand All @@ -621,7 +640,7 @@ mod tests {

#[test]
fn list_split_ranges_are_tracked_correctly() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(1);
let split_coinbase_output = TransactionTemplate {
Expand All @@ -647,7 +666,7 @@ mod tests {

#[test]
fn list_merge_ranges_are_tracked_correctly() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(2);
let merge_coinbase_outputs = TransactionTemplate {
Expand All @@ -671,7 +690,7 @@ mod tests {

#[test]
fn list_fee_paying_transaction_range() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(1);
let fee_paying_tx = TransactionTemplate {
Expand Down Expand Up @@ -705,7 +724,7 @@ mod tests {

#[test]
fn list_two_fee_paying_transaction_range() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(2);
let first_fee_paying_tx = TransactionTemplate {
Expand Down Expand Up @@ -740,7 +759,7 @@ mod tests {

#[test]
fn list_null_output() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(1);
let no_value_output = TransactionTemplate {
Expand All @@ -760,7 +779,7 @@ mod tests {

#[test]
fn list_null_input() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

context.rpc_server.mine_blocks(1);
let no_value_output = TransactionTemplate {
Expand Down Expand Up @@ -788,7 +807,7 @@ mod tests {

#[test]
fn list_spent_output() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
context.rpc_server.mine_blocks(1);
context.rpc_server.broadcast_tx(TransactionTemplate {
input_slots: &[(1, 0, 0)],
Expand All @@ -806,7 +825,7 @@ mod tests {

#[test]
fn list_unknown_output() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");

assert_eq!(
context
Expand All @@ -823,7 +842,7 @@ mod tests {

#[test]
fn find_first_ordinal() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
assert_eq!(
context.index.find(0).unwrap().unwrap(),
SatPoint {
Expand All @@ -837,7 +856,7 @@ mod tests {

#[test]
fn find_second_ordinal() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
assert_eq!(
context.index.find(1).unwrap().unwrap(),
SatPoint {
Expand All @@ -851,7 +870,7 @@ mod tests {

#[test]
fn find_first_ordinal_of_second_block() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
context.rpc_server.mine_blocks(1);
context.index.update().unwrap();
assert_eq!(
Expand All @@ -867,13 +886,13 @@ mod tests {

#[test]
fn find_unmined_ordinal() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
assert_eq!(context.index.find(50 * COIN_VALUE).unwrap(), None);
}

#[test]
fn find_first_satoshi_spent_in_second_block() {
let context = Context::new();
let context = Context::with_args("--index-ordinals");
context.rpc_server.mine_blocks(1);
let spend_txid = context.rpc_server.broadcast_tx(TransactionTemplate {
input_slots: &[(1, 0, 0)],
Expand Down
106 changes: 55 additions & 51 deletions src/index/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub struct Updater {
cache: HashMap<[u8; 36], Vec<u8>>,
chain: Chain,
height: u64,
index_ordinals: bool,
ordinal_ranges_since_flush: u64,
outputs_cached: u64,
outputs_inserted_since_flush: u64,
Expand Down Expand Up @@ -36,6 +37,7 @@ impl Updater {
cache: HashMap::new(),
chain: index.chain,
height,
index_ordinals: index.index_ordinals,
ordinal_ranges_since_flush: 0,
outputs_cached: 0,
outputs_inserted_since_flush: 0,
Expand Down Expand Up @@ -230,67 +232,69 @@ impl Updater {
}
}

let mut coinbase_inputs = VecDeque::new();
if self.index_ordinals {
let mut coinbase_inputs = VecDeque::new();

let h = Height(self.height);
if h.subsidy() > 0 {
let start = h.starting_ordinal();
coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n()));
self.ordinal_ranges_since_flush += 1;
}
let h = Height(self.height);
if h.subsidy() > 0 {
let start = h.starting_ordinal();
coinbase_inputs.push_front((start.n(), (start + h.subsidy()).n()));
self.ordinal_ranges_since_flush += 1;
}

for (tx_offset, tx) in block.txdata.iter().enumerate().skip(1) {
let txid = tx.txid();
for (tx_offset, tx) in block.txdata.iter().enumerate().skip(1) {
let txid = tx.txid();

log::trace!("Indexing transaction {tx_offset}…");
log::trace!("Indexing transaction {tx_offset}…");

let mut input_ordinal_ranges = VecDeque::new();
let mut input_ordinal_ranges = VecDeque::new();

for input in &tx.input {
let key = encode_outpoint(input.previous_output);
for input in &tx.input {
let key = encode_outpoint(input.previous_output);

let ordinal_ranges = match self.cache.remove(&key) {
Some(ordinal_ranges) => {
self.outputs_cached += 1;
ordinal_ranges
}
None => outpoint_to_ordinal_ranges
.remove(&key)?
.ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))?
.to_value()
.to_vec(),
};
let ordinal_ranges = match self.cache.remove(&key) {
Some(ordinal_ranges) => {
self.outputs_cached += 1;
ordinal_ranges
}
None => outpoint_to_ordinal_ranges
.remove(&key)?
.ok_or_else(|| anyhow!("Could not find outpoint {} in index", input.previous_output))?
.to_value()
.to_vec(),
};

for chunk in ordinal_ranges.chunks_exact(11) {
input_ordinal_ranges.push_back(Index::decode_ordinal_range(chunk.try_into().unwrap()));
for chunk in ordinal_ranges.chunks_exact(11) {
input_ordinal_ranges.push_back(Index::decode_ordinal_range(chunk.try_into().unwrap()));
}
}
}

self.index_transaction(
txid,
tx,
&mut ordinal_to_satpoint,
&mut ordinal_to_inscription_txid,
&mut txid_to_inscription,
&mut input_ordinal_ranges,
&mut ordinal_ranges_written,
&mut outputs_in_block,
)?;

coinbase_inputs.extend(input_ordinal_ranges);
}
self.index_transaction(
txid,
tx,
&mut ordinal_to_satpoint,
&mut ordinal_to_inscription_txid,
&mut txid_to_inscription,
&mut input_ordinal_ranges,
&mut ordinal_ranges_written,
&mut outputs_in_block,
)?;

coinbase_inputs.extend(input_ordinal_ranges);
}

if let Some(tx) = block.coinbase() {
self.index_transaction(
tx.txid(),
tx,
&mut ordinal_to_satpoint,
&mut ordinal_to_inscription_txid,
&mut txid_to_inscription,
&mut coinbase_inputs,
&mut ordinal_ranges_written,
&mut outputs_in_block,
)?;
if let Some(tx) = block.coinbase() {
self.index_transaction(
tx.txid(),
tx,
&mut ordinal_to_satpoint,
&mut ordinal_to_inscription_txid,
&mut txid_to_inscription,
&mut coinbase_inputs,
&mut ordinal_ranges_written,
&mut outputs_in_block,
)?;
}
}

height_to_block_hash.insert(&self.height, &block.block_hash().as_hash().into_inner())?;
Expand Down
Loading

0 comments on commit 7e696ef

Please sign in to comment.