Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
/target
/test-times.txt
/tmp
inscriptions_snapshot.csv
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
`ord`
=====
First of all, install rust and build `ord` from source (see [building section](#building)) and then start your `bitcoind` daemon.
On the examples we are going to use the `signet` settings, starting by the `bitcoin.conf` file for the bitcoin node:
```bash
# ~/.bitcoin/bitcoin.conf
rpcallowip=127.0.0.1
txindex=1
chain=signet
server=1

[signet]
rpcport=38332
```

**New features:**
* Added the endpoint `/inscription_by_number/:number`
To use this endpoint start the `ord` server
```
sudo ./target/release/ord -s --cookie-file ~/.bitcoin/signet/.cookie --rpc-url 127.0.0.1:38332 server
```

* Added the endpoint `/block_json/:height`

* Added the snapshot cli command `ord snapshot`
To use this cli run
```
sudo ./target/release/ord -s --cookie-file ~/.bitcoin/signet/.cookie --rpc-url 127.0.0.1:38332 snapshot > inscriptions_snapshot.csv
```

* Added a set of queries cli commands `ord query <sat|block|inscription>`

`ord`
=====
`ord` is an index, block explorer, and command-line wallet. It is experimental
software with no warranty. See [LICENSE](LICENSE) for more details.

Expand Down
15 changes: 15 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ impl Index {
})
}

pub(crate) fn get_inscription_ids_by_number(
&self,
) -> Result<HashMap<InscriptionId, u64>> {
let map: HashMap<InscriptionId, u64> = HashMap::from_iter(
self
.database
.begin_read()?
.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?
.range(0..)?
.map(|(n, id)| (Entry::load(*id.value()), n.value()))
);

Ok(map)
}

pub(crate) fn get_unspent_outputs(&self, _wallet: Wallet) -> Result<BTreeMap<OutPoint, Amount>> {
let mut utxos = BTreeMap::new();
utxos.extend(
Expand Down
8 changes: 8 additions & 0 deletions src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub mod subsidy;
pub mod supply;
pub mod traits;
pub mod wallet;
pub mod snapshot;
pub mod query;

fn print_json(output: impl Serialize) -> Result {
serde_json::to_writer_pretty(io::stdout(), &output)?;
Expand Down Expand Up @@ -45,6 +47,10 @@ pub(crate) enum Subcommand {
Traits(traits::Traits),
#[clap(subcommand, about = "Wallet commands")]
Wallet(wallet::Wallet),
#[clap(about = "Take a snapshot of current indexed inscriptions")]
Snapshot,
#[clap(subcommand, about = "Database query commands")]
Query(query::Query),
}

impl Subcommand {
Expand All @@ -67,6 +73,8 @@ impl Subcommand {
Self::Supply => supply::run(),
Self::Traits(traits) => traits.run(),
Self::Wallet(wallet) => wallet.run(options),
Self::Snapshot => snapshot::run(options),
Self::Query(query) => query.run(options),
}
}
}
25 changes: 25 additions & 0 deletions src/subcommand/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::*;

pub(crate) mod inscription;
pub(crate) mod sat;
pub(crate) mod block;

#[derive(Debug, Parser)]
pub(crate) enum Query {
#[clap(about = "Display information about an inscription")]
Inscription,
#[clap(about = "Display information about a satoshi")]
Sat,
#[clap(about = "Display information about a block")]
Block(block::Block),
}

impl Query {
pub(crate) fn run(self, options: Options) -> Result {
match self {
Self::Inscription => inscription::run(options),
Self::Sat => sat::run(options),
Self::Block(block) => block.run(options),
}
}
}
22 changes: 22 additions & 0 deletions src/subcommand/query/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use super::*;

#[derive(Debug, Parser)]
pub(crate) struct Block {
#[clap(help = "Block number")]
pub(crate) height: u64,
}

impl Block {
pub(crate) fn run(self, options: Options) -> Result {
let index = Index::open(&options)?;
index.update()?;

if let Some(block) = index.get_block_by_height(self.height)?{
print_json(block)?;
} else {
print_json({})?;
}

Ok(())
}
}
40 changes: 40 additions & 0 deletions src/subcommand/query/inscription.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use super::*;

pub(crate) fn run(_options: Options) -> Result {
println!("[subcommand::query::inscription]: Not implemented yet.");
/*
let index = Index::open(&options)?;
index.update()?;


let inscription_id = index.get_inscription_id_by_inscription_number(666)?.unwrap();
let entry = index.get_inscription_entry(inscription_id)?.unwrap();
let inscription = index.get_inscription_by_id(inscription_id)?.unwrap();
let satpoint = index.get_inscription_satpoint_by_id(inscription_id)?.unwrap();

let output = index
.get_transaction(satpoint.outpoint.txid)?.unwrap()
.output
.into_iter()
.nth(satpoint.outpoint.vout.try_into().unwrap()).unwrap();

let previous = if let Some(previous) = entry.number.checked_sub(1) {
Some(
index
.get_inscription_id_by_inscription_number(previous)?.unwrap()
)
} else {
None
};

let next = index.get_inscription_id_by_inscription_number(entry.number + 1)?.unwrap();

print_json(inscription_id);
print_json(satpoint);
print_json(output);
print_json(previous);
print_json(next);
*/

Ok(())
}
7 changes: 7 additions & 0 deletions src/subcommand/query/sat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use super::*;

pub(crate) fn run(_options: Options) -> Result {
println!("[subcommand::query::sat]: Not implemented yet.");

Ok(())
}
28 changes: 27 additions & 1 deletion src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use {
http::{header, HeaderMap, HeaderValue, StatusCode, Uri},
response::{IntoResponse, Redirect, Response},
routing::get,
Router, TypedHeader,
Router, TypedHeader, Json
},
axum_server::Handle,
rust_embed::RustEmbed,
Expand Down Expand Up @@ -148,6 +148,7 @@ impl Server {
.route("/", get(Self::home))
.route("/block-count", get(Self::block_count))
.route("/block/:query", get(Self::block))
.route("/block_json/:query", get(Self::block_json))
.route("/bounties", get(Self::bounties))
.route("/clock", get(Self::clock))
.route("/content/:inscription_id", get(Self::content))
Expand All @@ -156,6 +157,7 @@ impl Server {
.route("/feed.xml", get(Self::feed))
.route("/input/:block/:transaction/:input", get(Self::input))
.route("/inscription/:inscription_id", get(Self::inscription))
.route("/inscription_by_number/:inscription_number", get(Self::inscription_by_number))
.route("/inscriptions", get(Self::inscriptions))
.route("/inscriptions/:from", get(Self::inscriptions_from))
.route("/install.sh", get(Self::install_script))
Expand Down Expand Up @@ -479,6 +481,17 @@ impl Server {
Redirect::to("https://raw.githubusercontent.com/casey/ord/master/install.sh")
}

async fn block_json(
Extension(index): Extension<Arc<Index>>,
Path(DeserializeFromStr(height)): Path<DeserializeFromStr<u64>>
) -> ServerResult<Json<Block>> {
let block = index
.get_block_by_height(height)?
.ok_or_not_found(|| format!("block {height}"))?;

Ok(Json(block))
}

async fn block(
Extension(page_config): Extension<Arc<PageConfig>>,
Extension(index): Extension<Arc<Index>>,
Expand Down Expand Up @@ -943,6 +956,19 @@ impl Server {
)
}

async fn inscription_by_number(
Extension(page_config): Extension<Arc<PageConfig>>,
Extension(index): Extension<Arc<Index>>,
Path(inscription_number): Path<u64>,
) -> ServerResult<PageHtml<InscriptionHtml>>{

let inscription_id = index
.get_inscription_id_by_inscription_number(inscription_number)?
.ok_or_not_found(|| format!("inscription number {inscription_number}"))?;

Self::inscription(Extension(page_config), Extension(index), Path(inscription_id)).await
}

async fn inscriptions(
Extension(page_config): Extension<Arc<PageConfig>>,
Extension(index): Extension<Arc<Index>>,
Expand Down
39 changes: 39 additions & 0 deletions src/subcommand/snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use super::*;

struct SnapshotData {
inscription_number: u64,
inscription_id: InscriptionId,
transaction_id: Txid,
satoshi_location: SatPoint,
}

pub(crate) fn run(options: Options) -> Result {
let index = Index::open(&options)?;
index.update()?;

let inscriptions = index.get_inscriptions(None)?;
let inscription_numbers = index.get_inscription_ids_by_number()?;

let mut snapshot_rows: Vec<SnapshotData> = vec![];

for (satpoint, id) in inscriptions {
let row = SnapshotData {
inscription_number: inscription_numbers[&id],
inscription_id: id,
transaction_id: id.txid,
satoshi_location: satpoint,
};

snapshot_rows.push(row);
}

snapshot_rows.sort_by(|a, b| a.inscription_number.cmp(&b.inscription_number));


println!("inscription_number, inscription_id, transaction_id, satoshi_location");
for row in snapshot_rows {
println!("{}, {}, {}, {}", row.inscription_number, row.inscription_id, row.transaction_id, row.satoshi_location);
}

Ok(())
}