Skip to content

Commit

Permalink
Add config (ordinals#1392)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey committed Jan 30, 2023
1 parent 21292a7 commit 6921bd8
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 9 deletions.
20 changes: 20 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 @@ -45,6 +45,7 @@ rustls = "0.20.6"
rustls-acme = { version = "0.5.0", features = ["axum"] }
serde = { version = "1.0.137", features = ["derive"] }
serde_json = { version = "1.0.81" }
serde_yaml = "0.9.17"
sys-info = "0.9.1"
tempfile = "3.2.0"
tokio = { version = "1.17.0", features = ["rt-multi-thread"] }
Expand Down
1 change: 1 addition & 0 deletions deploy/ord.service
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Environment=RUST_LOG=info
ExecStart=/usr/local/bin/ord \
--bitcoin-data-dir /var/lib/bitcoind \
--data-dir /var/lib/ord \
--config /var/lib/ord/ord.yaml \
--chain ${CHAIN} \
--index-sats \
server \
Expand Down
35 changes: 35 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::*;

#[derive(Deserialize, Default, PartialEq, Debug)]
pub(crate) struct Config {
pub(crate) hidden: HashSet<InscriptionId>,
}

impl Config {
pub(crate) fn is_hidden(&self, inscription_id: InscriptionId) -> bool {
self.hidden.contains(&inscription_id)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn inscriptions_can_be_hidden() {
let a = "8d363b28528b0cb86b5fd48615493fb175bdf132d2a3d20b4251bba3f130a5abi0"
.parse::<InscriptionId>()
.unwrap();

let b = "8d363b28528b0cb86b5fd48615493fb175bdf132d2a3d20b4251bba3f130a5abi1"
.parse::<InscriptionId>()
.unwrap();

let config = Config {
hidden: iter::once(a).collect(),
};

assert!(config.is_hidden(a));
assert!(!config.is_hidden(b));
}
}
2 changes: 1 addition & 1 deletion src/inscription_id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::*;

#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
pub struct InscriptionId {
pub(crate) txid: Txid,
pub(crate) index: u32,
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use {
self::{
arguments::Arguments,
blocktime::Blocktime,
config::Config,
decimal::Decimal,
degree::Degree,
deserialize_from_str::DeserializeFromStr,
Expand Down Expand Up @@ -53,7 +54,8 @@ use {
env,
ffi::OsString,
fmt::{self, Display, Formatter},
fs, io,
fs::{self, File},
io,
net::{TcpListener, ToSocketAddrs},
ops::{Add, AddAssign, Sub},
path::{Path, PathBuf},
Expand Down Expand Up @@ -95,6 +97,7 @@ macro_rules! tprintln {
mod arguments;
mod blocktime;
mod chain;
mod config;
mod decimal;
mod degree;
mod deserialize_from_str;
Expand Down
43 changes: 43 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub(crate) struct Options {
help = "Use <CHAIN>."
)]
pub(crate) chain_argument: Chain,
#[clap(long, help = "Load configuration from <CONFIG>.")]
pub(crate) config: Option<PathBuf>,
#[clap(long, help = "Load Bitcoin Core RPC cookie file from <COOKIE_FILE>.")]
pub(crate) cookie_file: Option<PathBuf>,
#[clap(long, help = "Store index in <DATA_DIR>.")]
Expand Down Expand Up @@ -111,6 +113,13 @@ impl Options {
Ok(self.chain().join_with_data_dir(&base))
}

pub(crate) fn load_config(&self) -> Result<Config> {
match &self.config {
Some(path) => Ok(serde_yaml::from_reader(File::open(path)?)?),
None => Ok(Default::default()),
}
}

fn format_bitcoin_core_version(version: usize) -> String {
format!(
"{}.{}.{}",
Expand Down Expand Up @@ -507,4 +516,38 @@ mod tests {
"foo"
)
}

#[test]
fn default_config_is_returned_if_config_option_is_not_passed() {
assert_eq!(
Arguments::try_parse_from(["ord", "index"])
.unwrap()
.options
.load_config()
.unwrap(),
Default::default()
);
}

#[test]
fn config_is_loaded_from_config_option_path() {
let id = "8d363b28528b0cb86b5fd48615493fb175bdf132d2a3d20b4251bba3f130a5abi0"
.parse::<InscriptionId>()
.unwrap();

let tempdir = TempDir::new().unwrap();
let path = tempdir.path().join("ord.yaml");
fs::write(&path, format!("hidden:\n- \"{id}\"")).unwrap();

assert_eq!(
Arguments::try_parse_from(["ord", "--config", path.to_str().unwrap(), "index",])
.unwrap()
.options
.load_config()
.unwrap(),
Config {
hidden: iter::once(id).collect(),
}
);
}
}
70 changes: 68 additions & 2 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ impl Server {
thread::sleep(Duration::from_millis(5000));
});

let config = options.load_config()?;

let router = Router::new()
.route("/", get(Self::home))
.route("/block-count", get(Self::block_count))
Expand Down Expand Up @@ -161,6 +163,7 @@ impl Server {
.route("/tx/:txid", get(Self::transaction))
.layer(Extension(index))
.layer(Extension(options.chain()))
.layer(Extension(Arc::new(config)))
.layer(SetResponseHeaderLayer::if_not_present(
header::CONTENT_SECURITY_POLICY,
HeaderValue::from_static("default-src 'self'"),
Expand Down Expand Up @@ -705,8 +708,13 @@ impl Server {

async fn content(
Extension(index): Extension<Arc<Index>>,
Extension(config): Extension<Arc<Config>>,
Path(inscription_id): Path<InscriptionId>,
) -> ServerResult<Response> {
if config.is_hidden(inscription_id) {
return Ok(PreviewUnknownHtml.into_response());
}

let inscription = index
.get_inscription_by_id(inscription_id)?
.ok_or_not_found(|| format!("inscription {inscription_id}"))?;
Expand Down Expand Up @@ -743,8 +751,13 @@ impl Server {

async fn preview(
Extension(index): Extension<Arc<Index>>,
Extension(config): Extension<Arc<Config>>,
Path(inscription_id): Path<InscriptionId>,
) -> ServerResult<Response> {
if config.is_hidden(inscription_id) {
return Ok(PreviewUnknownHtml.into_response());
}

let inscription = index
.get_inscription_by_id(inscription_id)?
.ok_or_not_found(|| format!("inscription {inscription_id}"))?;
Expand Down Expand Up @@ -915,8 +928,22 @@ mod tests {
}

fn new_with_args(ord_args: &[&str], server_args: &[&str]) -> Self {
let bitcoin_rpc_server = test_bitcoincore_rpc::spawn();
Self::new_server(test_bitcoincore_rpc::spawn(), None, ord_args, server_args)
}

fn new_with_bitcoin_rpc_server_and_config(
bitcoin_rpc_server: test_bitcoincore_rpc::Handle,
config: String,
) -> Self {
Self::new_server(bitcoin_rpc_server, Some(config), &[], &[])
}

fn new_server(
bitcoin_rpc_server: test_bitcoincore_rpc::Handle,
config: Option<String>,
ord_args: &[&str],
server_args: &[&str],
) -> Self {
let tempdir = TempDir::new().unwrap();

let cookiefile = tempdir.path().join("cookie");
Expand All @@ -931,8 +958,17 @@ mod tests {

let url = Url::parse(&format!("http:https://127.0.0.1:{port}")).unwrap();

let config_args = match config {
Some(config) => {
let config_path = tempdir.path().join("ord.yaml");
fs::write(&config_path, config).unwrap();
format!("--config {}", config_path.display())
}
None => "".to_string(),
};

let (options, server) = parse_server_args(&format!(
"ord --chain regtest --rpc-url {} --cookie-file {} --data-dir {} {} server --http-port {} --address 127.0.0.1 {}",
"ord --chain regtest --rpc-url {} --cookie-file {} --data-dir {} {config_args} {} server --http-port {} --address 127.0.0.1 {}",
bitcoin_rpc_server.url(),
cookiefile.to_str().unwrap(),
tempdir.path().to_str().unwrap(),
Expand Down Expand Up @@ -2400,4 +2436,34 @@ mod tests {
"br"
);
}

#[test]
fn inscriptions_can_be_hidden_with_config() {
let bitcoin_rpc_server = test_bitcoincore_rpc::spawn();
bitcoin_rpc_server.mine_blocks(1);
let txid = bitcoin_rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0)],
witness: inscription("text/plain;charset=utf-8", "hello").to_witness(),
..Default::default()
});
let inscription = InscriptionId::from(txid);
bitcoin_rpc_server.mine_blocks(1);

let server = TestServer::new_with_bitcoin_rpc_server_and_config(
bitcoin_rpc_server,
format!("\"hidden\":\n - {inscription}"),
);

server.assert_response(
format!("/preview/{inscription}"),
StatusCode::OK,
&fs::read_to_string("templates/preview-unknown.html").unwrap(),
);

server.assert_response(
format!("/content/{inscription}"),
StatusCode::OK,
&fs::read_to_string("templates/preview-unknown.html").unwrap(),
);
}
}
2 changes: 1 addition & 1 deletion src/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub(crate) use {
super::*, bitcoin::Witness, pretty_assertions::assert_eq as pretty_assert_eq,
super::*, bitcoin::Witness, pretty_assertions::assert_eq as pretty_assert_eq, std::iter,
test_bitcoincore_rpc::TransactionTemplate, unindent::Unindent,
};

Expand Down
2 changes: 1 addition & 1 deletion tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ fn inscription_content() {
rpc_server.mine_blocks(1);

let response =
TestServer::spawn_with_args(&rpc_server, &[]).request(&format!("/content/{inscription}"));
TestServer::spawn_with_args(&rpc_server, &[]).request(format!("/content/{inscription}"));

assert_eq!(response.status(), StatusCode::OK);
assert_eq!(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl TestServer {
assert_regex_match!(response.text().unwrap(), regex.as_ref());
}

pub(crate) fn request(&self, path: &str) -> Response {
pub(crate) fn request(&self, path: impl AsRef<str>) -> Response {
let client = Client::new(&self.rpc_url, Auth::None).unwrap();
let chain_block_count = client.get_block_count().unwrap() + 1;

Expand All @@ -94,7 +94,7 @@ impl TestServer {
thread::sleep(Duration::from_millis(25));
}

reqwest::blocking::get(self.url().join(path).unwrap()).unwrap()
reqwest::blocking::get(self.url().join(path.as_ref()).unwrap()).unwrap()
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/wallet/inscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn inscribe_creates_inscriptions() {
assert_eq!(rpc_server.descriptors().len(), 3);

let request =
TestServer::spawn_with_args(&rpc_server, &[]).request(&format!("/content/{inscription}"));
TestServer::spawn_with_args(&rpc_server, &[]).request(format!("/content/{inscription}"));

assert_eq!(request.status(), 200);
assert_eq!(
Expand Down

0 comments on commit 6921bd8

Please sign in to comment.