Skip to content

Commit

Permalink
Add ord rune publish
Browse files Browse the repository at this point in the history
  • Loading branch information
casey committed Oct 11, 2022
1 parent 85252d0 commit 3b8ef90
Show file tree
Hide file tree
Showing 21 changed files with 662 additions and 225 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ html-escaper = "0.2.0"
http = "0.2.6"
lazy_static = "1.4.0"
log = "0.4.14"
mime = "0.3.16"
mime_guess = "2.0.4"
rayon = "1.5.1"
redb = "0.7.0"
regex = "1.6.0"
reqwest = { version = "0.11.10", features = ["blocking"] }
rust-embed = "6.4.0"
rustls = "0.20.6"
rustls-acme = { version = "0.5.0", features = ["axum"] }
serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.81"
serde_json = { version = "1.0.81", features = ["arbitrary_precision"] }
sys-info = "0.9.1"
tokio = { version = "1.17.0", features = ["rt-multi-thread"] }
tokio-stream = "0.1.9"
Expand All @@ -49,7 +51,6 @@ tower-http = { version = "0.3.3", features = ["cors"] }
executable-path = "1.0.0"
nix = "0.25.0"
pretty_assertions = "1.2.1"
reqwest = { version = "0.11.10", features = ["blocking"] }
tempfile = "3.2.0"
test-bitcoincore-rpc = { path = "test-bitcoincore-rpc" }
unindent = "0.1.7"
Expand Down
6 changes: 3 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
watch +args='test':
cargo watch --clear --exec '{{args}}'

ci: clippy forbid
cargo fmt -- --check
cargo test --all
Expand All @@ -14,9 +17,6 @@ clippy:
bench:
cargo criterion

watch +args='test':
cargo watch --clear --exec '{{args}}'

install-dev-deps:
cargo install cargo-criterion

Expand Down
32 changes: 29 additions & 3 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ use {
super::*,
bitcoin::consensus::encode::deserialize,
bitcoin::BlockHeader,
bitcoincore_rpc::{json::GetBlockHeaderResult, Auth, Client, RpcApi},
bitcoincore_rpc::{json::GetBlockHeaderResult, Auth, Client},
rayon::iter::{IntoParallelRefIterator, ParallelIterator},
redb::WriteStrategy,
std::sync::atomic::{AtomicBool, Ordering},
};

mod rtx;

const HASH_TO_RUNE: TableDefinition<[u8; 32], str> = TableDefinition::new("HASH_TO_RUNE");
const HEIGHT_TO_HASH: TableDefinition<u64, [u8; 32]> = TableDefinition::new("HEIGHT_TO_HASH");
const ORDINAL_TO_SATPOINT: TableDefinition<u64, [u8; 44]> =
TableDefinition::new("ORDINAL_TO_SATPOINT");
const OUTPOINT_TO_ORDINAL_RANGES: TableDefinition<[u8; 36], [u8]> =
TableDefinition::new("OUTPOINT_TO_ORDINAL_RANGES");
const STATISTICS: TableDefinition<u64, u64> = TableDefinition::new("STATISTICS");
const ORDINAL_TO_SATPOINT: TableDefinition<u64, [u8; 44]> =
TableDefinition::new("ORDINAL_TO_SATPOINT");

fn encode_outpoint(outpoint: OutPoint) -> [u8; 36] {
let mut array = [0; 36];
Expand Down Expand Up @@ -124,6 +125,7 @@ impl Index {
tx
};

tx.open_table(HASH_TO_RUNE)?;
tx.open_table(HEIGHT_TO_HASH)?;
tx.open_table(ORDINAL_TO_SATPOINT)?;
tx.open_table(OUTPOINT_TO_ORDINAL_RANGES)?;
Expand Down Expand Up @@ -534,6 +536,30 @@ impl Index {
)
}

pub(crate) fn rune(&self, hash: sha256::Hash) -> Result<Option<Rune>> {
Ok(
self
.database
.begin_read()?
.open_table(HASH_TO_RUNE)?
.get(hash.as_inner())?
.map(serde_json::from_str)
.transpose()?,
)
}

pub(crate) fn insert_rune(&self, rune: &Rune) -> Result<(bool, sha256::Hash)> {
let json = serde_json::to_string(rune)?;
let hash = sha256::Hash::hash(json.as_ref());
let wtx = self.database.begin_write()?;
let created = wtx
.open_table(HASH_TO_RUNE)?
.insert(hash.as_inner(), &json)?
.is_none();
wtx.commit()?;
Ok((created, hash))
}

pub(crate) fn find(&self, ordinal: u64) -> Result<Option<SatPoint>> {
if self.height()? < Ordinal(ordinal).height() {
return Ok(None);
Expand Down
9 changes: 5 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ use {
options::Options,
ordinal::Ordinal,
rarity::Rarity,
rune::Rune,
sat_point::SatPoint,
subcommand::Subcommand,
tally::Tally,
},
anyhow::{anyhow, bail, Context, Error},
axum::{extract, http::StatusCode, response::Html, response::IntoResponse, routing::get, Router},
axum_server::Handle,
bitcoin::{
blockdata::constants::COIN_VALUE,
consensus::{Decodable, Encodable},
hash_types::BlockHash,
hashes::Hash,
hashes::{sha256, Hash},
Address, Block, Network, OutPoint, Transaction, TxOut, Txid,
},
bitcoincore_rpc::RpcApi,
chrono::{DateTime, NaiveDateTime, Utc},
clap::Parser,
derive_more::{Display, FromStr},
Expand Down Expand Up @@ -72,6 +72,7 @@ mod index;
mod options;
mod ordinal;
mod rarity;
mod rune;
mod sat_point;
mod subcommand;
mod tally;
Expand All @@ -84,7 +85,7 @@ const SUBSIDY_HALVING_INTERVAL: u64 =
const CYCLE_EPOCHS: u64 = 6;

static INTERRUPTS: AtomicU64 = AtomicU64::new(0);
static LISTENERS: Mutex<Vec<Handle>> = Mutex::new(Vec::new());
static LISTENERS: Mutex<Vec<axum_server::Handle>> = Mutex::new(Vec::new());

fn main() {
env_logger::init();
Expand Down
8 changes: 8 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ impl Options {
Client::new(&rpc_url, Auth::CookieFile(cookie_file))
.context("Failed to connect to Bitcoin Core RPC at {rpc_url}")
}

pub(crate) fn bitcoin_rpc_client_mainnet_forbidden(&self, command: &str) -> Result<Client> {
let client = self.bitcoin_rpc_client()?;
if self.chain.network() == Network::Bitcoin || client.get_blockchain_info()?.chain == "main" {
bail!("`{command}` is unstable and not yet supported on mainnet.");
}
Ok(client)
}
}

#[cfg(test)]
Expand Down
8 changes: 8 additions & 0 deletions src/rune.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use super::*;

#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct Rune {
pub(crate) name: String,
pub(crate) network: Network,
pub(crate) ordinal: Ordinal,
}
6 changes: 5 additions & 1 deletion src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod info;
mod list;
mod parse;
mod range;
mod rune;
mod server;
mod supply;
mod traits;
Expand All @@ -21,6 +22,8 @@ pub(crate) enum Subcommand {
List(list::List),
Parse(parse::Parse),
Range(range::Range),
#[clap(subcommand)]
Rune(rune::Rune),
Server(server::Server),
Supply,
Traits(traits::Traits),
Expand All @@ -38,9 +41,10 @@ impl Subcommand {
Self::List(list) => list.run(options),
Self::Parse(parse) => parse.run(),
Self::Range(range) => range.run(),
Self::Rune(rune) => rune.run(options),
Self::Server(server) => {
let index = Arc::new(Index::open(&options)?);
let handle = Handle::new();
let handle = axum_server::Handle::new();
LISTENERS.lock().unwrap().push(handle.clone());
server.run(options, index, handle)
}
Expand Down
16 changes: 16 additions & 0 deletions src/subcommand/rune.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use super::*;

mod publish;

#[derive(Debug, Parser)]
pub(crate) enum Rune {
Publish(publish::Publish),
}

impl Rune {
pub(crate) fn run(self, options: Options) -> Result<()> {
match self {
Self::Publish(publish) => publish.run(options),
}
}
}
51 changes: 51 additions & 0 deletions src/subcommand/rune/publish.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use {super::*, reqwest::Url};

#[derive(Debug, Parser)]
pub(crate) struct Publish {
#[clap(long, help = "Give rune <NAME>.")]
name: String,
#[clap(long, help = "Inscribe rune on <ORDINAL>.")]
ordinal: Ordinal,
#[clap(
long,
default_value = "https://ordinals.com/",
help = "Publish rune to <PUBLISH_URL>."
)]
publish_url: Url,
}

impl Publish {
pub(crate) fn run(self, options: Options) -> Result {
options.bitcoin_rpc_client_mainnet_forbidden("ord rune publish")?;

let rune = crate::Rune {
network: options.chain.network(),
name: self.name,
ordinal: self.ordinal,
};

let json = serde_json::to_string(&rune)?;

let url = self.publish_url.join("rune")?;

let response = reqwest::blocking::Client::new()
.put(url.clone())
.header(
reqwest::header::CONTENT_TYPE,
mime::APPLICATION_JSON.as_ref(),
)
.body(json)
.send()?;

let status = response.status();

if !status.is_success() {
bail!("Failed to post rune to `{}`:\n{}", url, response.text()?)
}

eprintln!("Rune published: {}", response.status());
println!("{}", response.text()?);

Ok(())
}
}
Loading

0 comments on commit 3b8ef90

Please sign in to comment.