diff --git a/CHANGELOG.md b/CHANGELOG.md index 51b1cbaf1..c848a6b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,17 @@ # v0.X.0 | WIP | A new beginning +![Image of BRK's Web App version 0.1.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/brk-v0.1.0.png) + Full rewrite -# [kibo-v0.5.0](https://github.com/kibo-money/kibo/tree/eea56d394bf92c62c81da8b78b8c47ea730683f5) | [873199](https://mempool.space/block/0000000000000000000270925aa6a565be92e13164565a3f7994ca1966e48050) - 2024/12/04 +# [kibo-v0.5.0](https://github.com/bitcoinresearchkit/brk/tree/eea56d394bf92c62c81da8b78b8c47ea730683f5) | [873199](https://mempool.space/block/0000000000000000000270925aa6a565be92e13164565a3f7994ca1966e48050) - 2024/12/04 -![Image of the kibo Web App version 0.5.0](https://github.com/kibo-money/kibo/blob/main/_assets/v0.5.0.jpg) +![Image of the kibo Web App version 0.5.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/kibo-v0.5.0.jpg) ## Datasets @@ -74,9 +76,9 @@ Full rewrite - Moved back to this repo -# [kibo-v0.4.0](https://github.com/kibo-money/kibo/tree/a64c544815d9ef785e2fc1323582f774f16b9200) | [861950](https://mempool.space/block/00000000000000000000530d0e30ccf7deeace122dcc99f2668a06c6dad83629) - 2024/09/19 +# [kibo-v0.4.0](https://github.com/bitcoinresearchkit/brk/tree/a64c544815d9ef785e2fc1323582f774f16b9200) | [861950](https://mempool.space/block/00000000000000000000530d0e30ccf7deeace122dcc99f2668a06c6dad83629) - 2024/09/19 -![Image of the kibo Web App version 0.4.0](https://github.com/kibo-money/kibo/blob/main/_assets/v0.4.0.jpg) +![Image of the kibo Web App version 0.4.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/kibo-v0.4.0.jpg) ## Brand @@ -111,9 +113,9 @@ Full rewrite - Added serving of the website - Improved `Cache-Control` behavior -# [kibo-v0.3.0](https://github.com/kibo-money/kibo/tree/b68b016091c45b071218fba01bac5b76e8eaf18c) | [853930](https://mempool.space/block/00000000000000000002eb5e9a7950ca2d5d98bd1ed28fc9098aa630d417985d) - 2024/07/26 +# [kibo-v0.3.0](https://github.com/bitcoinresearchkit/brk/tree/b68b016091c45b071218fba01bac5b76e8eaf18c) | [853930](https://mempool.space/block/00000000000000000002eb5e9a7950ca2d5d98bd1ed28fc9098aa630d417985d) - 2024/07/26 -![Image of the Satonomics Web App version 0.3.0](https://github.com/kibo-money/kibo/blob/main/_assets/v0.3.0.jpg) +![Image of the Satonomics Web App version 0.3.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/satonomics-v0.3.0.jpg) ## Parser @@ -190,9 +192,9 @@ Full rewrite - Only run with a watcher if `cargo watch` is available - Removed id_to_path file in favor for only `paths.d.ts` in `app/src/types` -# [kibo-v0.2.0](https://github.com/kibo-money/kibo/tree/248187889283597c5dbb806292297453c25e97b8) | [851286](https://mempool.space/block/0000000000000000000281ca7f1bf8c50702bfca168c7af1bdc67c977c1ac8ed) - 2024/07/08 +# [kibo-v0.2.0](https://github.com/bitcoinresearchkit/brk/tree/248187889283597c5dbb806292297453c25e97b8) | [851286](https://mempool.space/block/0000000000000000000281ca7f1bf8c50702bfca168c7af1bdc67c977c1ac8ed) - 2024/07/08 -![Image of the Satonomics Web App version 0.2.0](https://github.com/kibo-money/kibo/blob/main/_assets/v0.2.0.jpg) +![Image of the Satonomics Web App version 0.2.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/satonomics-v0.2.0.jpg) ## App @@ -226,9 +228,9 @@ Full rewrite - Fixed ulimit only being run in Mac OS instead of whenever the program is detected -# [kibo-v0.1.1](https://github.com/kibo-money/kibo/tree/e55b5195a9de9aea306903c94ed63cb1720fda5f) | [849240](https://mempool.space/block/000000000000000000002b8653988655071c07bb5f7181c038f9326bc86db741) - 2024/06/24 +# [kibo-v0.1.1](https://github.com/bitcoinresearchkit/brk/tree/e55b5195a9de9aea306903c94ed63cb1720fda5f) | [849240](https://mempool.space/block/000000000000000000002b8653988655071c07bb5f7181c038f9326bc86db741) - 2024/06/24 -![Image of the Satonomics Web App version 0.1.1](https://github.com/kibo-money/kibo/blob/main/_assets/v0.1.1.jpg) +![Image of the Satonomics Web App version 0.1.1](https://github.com/bitcoinresearchkit/brk/blob/main/assets/satonomics-v0.1.1.jpg) ## Parser @@ -276,10 +278,10 @@ Full rewrite - Deleted old price datasets and their backups -# [kibo-v0.1.0](https://github.com/kibo-money/kibo/tree/a1a576d088c8f83ed32d48753a7611f70a964574) | [848642](https://mempool.space/block/000000000000000000020be5761d70751252219a9557f55e91ecdfb86c4e026a) - 2024/06/19 +# [kibo-v0.1.0](https://github.com/bitcoinresearchkit/brk/tree/a1a576d088c8f83ed32d48753a7611f70a964574) | [848642](https://mempool.space/block/000000000000000000020be5761d70751252219a9557f55e91ecdfb86c4e026a) - 2024/06/19 -![Image of the Satonomics Web App version 0.1.0](https://github.com/kibo-money/kibo/blob/main/_assets/v0.1.0.jpg) +![Image of the Satonomics Web App version 0.1.0](https://github.com/bitcoinresearchkit/brk/blob/main/assets/satonomics-v0.1.0.jpg) # kibo-v0.0.1 | [835444](https://mempool.space/block/000000000000000000009f93907a0dd83c080d5585cc7ec82c076d45f6d7c872) - 2024/03/20 -![Image of the Satonomics Web App version 0.0.X](https://github.com/kibo-money/kibo/blob/main/_assets/v0.0.X.jpg) +![Image of the Satonomics Web App version 0.0.X](https://github.com/bitcoinresearchkit/brk/blob/main/assets/satonomics-v0.0.1.jpg) diff --git a/Cargo.lock b/Cargo.lock index 840ab9f23..c0325420a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -454,6 +454,7 @@ dependencies = [ "brk_indexer", "brk_interface", "brk_logger", + "brk_mcp", "brk_parser", "brk_server", "brk_state", @@ -482,7 +483,6 @@ dependencies = [ "brk_exit", "brk_fetcher", "brk_indexer", - "brk_interface", "brk_logger", "brk_parser", "brk_server", @@ -492,7 +492,6 @@ dependencies = [ "color-eyre", "log", "serde", - "tabled", "tokio", "toml", ] @@ -606,6 +605,17 @@ dependencies = [ "log", ] +[[package]] +name = "brk_mcp" +version = "0.0.66" +dependencies = [ + "axum", + "brk_interface", + "brk_rmcp", + "log", + "tracing", +] + [[package]] name = "brk_parser" version = "0.0.66" @@ -982,8 +992,8 @@ dependencies = [ "brk_indexer", "brk_interface", "brk_logger", + "brk_mcp", "brk_parser", - "brk_rmcp", "brk_vec", "clap", "clap_derive", @@ -1014,7 +1024,6 @@ dependencies = [ name = "brk_store" version = "0.0.66" dependencies = [ - "arc-swap", "brk_core", "byteview", "fjall", @@ -2530,9 +2539,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" [[package]] name = "oxc" diff --git a/Cargo.toml b/Cargo.toml index 0ea75d29d..4fb913b48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ brk_fetcher = { version = "0.0.66", path = "crates/brk_fetcher" } brk_indexer = { version = "0.0.66", path = "crates/brk_indexer" } brk_interface = { version = "0.0.66", path = "crates/brk_interface" } brk_logger = { version = "0.0.66", path = "crates/brk_logger" } +brk_mcp = { version = "0.0.66", path = "crates/brk_mcp" } brk_parser = { version = "0.0.66", path = "crates/brk_parser" } brk_rmcp = { version = "0.1.7", features = ["transport-streamable-http-server", "transport-worker"]} brk_server = { version = "0.0.66", path = "crates/brk_server" } diff --git a/README.md b/README.md index 35586e70a..c42a5c4c1 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,8 @@ In contrast, existing alternatives tend to be either [very costly](https://studi - [`brk_exit`](https://crates.io/crates/brk_exit): An exit blocker built on top of ctrlc - [`brk_fetcher`](https://crates.io/crates/brk_fetcher): A Bitcoin price fetcher - [`brk_indexer`](https://crates.io/crates/brk_indexer): A Bitcoin Core indexer built on top of brk_parser -- [`brk_logger`](https://crates.io/crates/brk_logger): A clean logger used in the Bitcoin Research Kit. +- [`brk_logger`](https://crates.io/crates/brk_logger): A clean logger used in the Bitcoin Research Kit +- [`brk_mcp`](https://crates.io/crates/brk_mcp): A Model Context Protocol (MCP) which gives LLMs access to all available tools in BRK - [`brk_parser`](https://crates.io/crates/brk_parser): A very fast Bitcoin Core block parser and iterator built on top of bitcoin-rust - [`brk_interface`](https://crates.io/crates/brk_interface): An interface to BRK's engine - [`brk_server`](https://crates.io/crates/brk_server): A server that serves Bitcoin data and swappable front-ends, built on top of `brk_indexer`, `brk_fetcher` and `brk_computer` diff --git a/assets/brk-v0.1.0.png b/assets/brk-v0.1.0.png new file mode 100644 index 000000000..ee08d6a38 Binary files /dev/null and b/assets/brk-v0.1.0.png differ diff --git a/assets/kibo-v0.4.0.jpg b/assets/kibo-v0.4.0.jpg new file mode 100644 index 000000000..39ed0ca34 Binary files /dev/null and b/assets/kibo-v0.4.0.jpg differ diff --git a/assets/kibo-v0.5.0.jpg b/assets/kibo-v0.5.0.jpg new file mode 100644 index 000000000..8e101192a Binary files /dev/null and b/assets/kibo-v0.5.0.jpg differ diff --git a/assets/satonomics-v0.0.1.jpg b/assets/satonomics-v0.0.1.jpg new file mode 100644 index 000000000..1c309fa21 Binary files /dev/null and b/assets/satonomics-v0.0.1.jpg differ diff --git a/assets/satonomics-v0.1.0.jpg b/assets/satonomics-v0.1.0.jpg new file mode 100644 index 000000000..c7e6d14b3 Binary files /dev/null and b/assets/satonomics-v0.1.0.jpg differ diff --git a/assets/satonomics-v0.1.1.jpg b/assets/satonomics-v0.1.1.jpg new file mode 100644 index 000000000..a999f808e Binary files /dev/null and b/assets/satonomics-v0.1.1.jpg differ diff --git a/assets/satonomics-v0.2.0.jpg b/assets/satonomics-v0.2.0.jpg new file mode 100644 index 000000000..34caf044e Binary files /dev/null and b/assets/satonomics-v0.2.0.jpg differ diff --git a/assets/satonomics-v0.3.0.jpg b/assets/satonomics-v0.3.0.jpg new file mode 100644 index 000000000..5b4cc8c5d Binary files /dev/null and b/assets/satonomics-v0.3.0.jpg differ diff --git a/crates/brk/Cargo.toml b/crates/brk/Cargo.toml index 502130097..99b24ae24 100644 --- a/crates/brk/Cargo.toml +++ b/crates/brk/Cargo.toml @@ -17,6 +17,7 @@ full = [ "fetcher", "indexer", "logger", + "mcp", "parser", "interface", "server", @@ -31,6 +32,7 @@ exit = ["brk_exit"] fetcher = ["brk_fetcher"] indexer = ["brk_indexer"] logger = ["brk_logger"] +mcp = ["brk_mcp"] parser = ["brk_parser"] interface = ["brk_interface"] server = ["brk_server"] @@ -47,6 +49,7 @@ brk_exit = { workspace = true, optional = true } brk_fetcher = { workspace = true, optional = true } brk_indexer = { workspace = true, optional = true } brk_logger = { workspace = true, optional = true } +brk_mcp = { workspace = true, optional = true } brk_parser = { workspace = true, optional = true } brk_interface = { workspace = true, optional = true } brk_server = { workspace = true, optional = true } diff --git a/crates/brk/src/lib.rs b/crates/brk/src/lib.rs index 1cea16918..12223db75 100644 --- a/crates/brk/src/lib.rs +++ b/crates/brk/src/lib.rs @@ -31,6 +31,10 @@ pub use brk_indexer as indexer; #[doc(inline)] pub use brk_logger as logger; +#[cfg(feature = "mcp")] +#[doc(inline)] +pub use brk_mcp as mcp; + #[cfg(feature = "parser")] #[doc(inline)] pub use brk_parser as parser; diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 18c6f5dfe..475097f47 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -16,7 +16,6 @@ brk_fetcher = { workspace = true } brk_indexer = { workspace = true } brk_logger = { workspace = true } brk_parser = { workspace = true } -brk_interface = { workspace = true } brk_server = { workspace = true } brk_vec = { workspace = true } clap = { workspace = true } @@ -24,7 +23,6 @@ clap_derive = { workspace = true } color-eyre = { workspace = true } log = { workspace = true } serde = { workspace = true } -tabled = { workspace = true } tokio = { workspace = true } toml = "0.8.23" diff --git a/crates/brk_core/src/structs/mod.rs b/crates/brk_core/src/structs/mod.rs index 509a1bb32..32142545b 100644 --- a/crates/brk_core/src/structs/mod.rs +++ b/crates/brk_core/src/structs/mod.rs @@ -61,7 +61,6 @@ pub use cents::*; pub use date::*; pub use dateindex::*; pub use decadeindex::*; -pub use decadeindex::*; pub use difficultyepoch::*; pub use dollars::*; pub use emptyoutputindex::*; diff --git a/crates/brk_mcp/Cargo.toml b/crates/brk_mcp/Cargo.toml new file mode 100644 index 000000000..6e63c2124 --- /dev/null +++ b/crates/brk_mcp/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "brk_mcp" +description = "A Model Context Protocol (MCP) which gives LLMs access to all available tools in BRK" +version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +axum = { workspace = true } +brk_interface = { workspace = true } +log = { workspace = true } +brk_rmcp = { workspace = true } +tracing = "0.1.41" diff --git a/crates/brk_mcp/README.md b/crates/brk_mcp/README.md new file mode 100644 index 000000000..679749860 --- /dev/null +++ b/crates/brk_mcp/README.md @@ -0,0 +1,3 @@ +# BRK MCP + +A Model Context Protocol (MCP) which gives LLMs access to all available tools in BRK diff --git a/crates/brk_server/src/mcp/api.rs b/crates/brk_mcp/src/lib.rs similarity index 96% rename from crates/brk_server/src/mcp/api.rs rename to crates/brk_mcp/src/lib.rs index e0dd28561..40d0ee568 100644 --- a/crates/brk_server/src/mcp/api.rs +++ b/crates/brk_mcp/src/lib.rs @@ -1,3 +1,8 @@ +#![doc = include_str!("../README.md")] +// #![doc = "\n## Example\n\n```rust"] +// #![doc = include_str!("../examples/main.rs")] +// #![doc = "```"] + use brk_interface::{IdParam, Interface, PaginatedIndexParam, PaginationParam, Params}; use brk_rmcp::{ Error as McpError, RoleServer, ServerHandler, @@ -10,15 +15,17 @@ use brk_rmcp::{ }; use log::info; +pub mod route; + #[derive(Clone)] -pub struct API { +pub struct MCP { interface: &'static Interface<'static>, } const VERSION: &str = env!("CARGO_PKG_VERSION"); #[tool(tool_box)] -impl API { +impl MCP { pub fn new(interface: &'static Interface<'static>) -> Self { Self { interface } } @@ -146,7 +153,7 @@ Get the running version of the Bitcoin Research Kit } #[tool(tool_box)] -impl ServerHandler for API { +impl ServerHandler for MCP { fn get_info(&self) -> ServerInfo { ServerInfo { protocol_version: ProtocolVersion::LATEST, diff --git a/crates/brk_server/src/mcp/mod.rs b/crates/brk_mcp/src/route.rs similarity index 85% rename from crates/brk_server/src/mcp/mod.rs rename to crates/brk_mcp/src/route.rs index dc1e8de0e..27f6bf2a5 100644 --- a/crates/brk_server/src/mcp/mod.rs +++ b/crates/brk_mcp/src/route.rs @@ -5,17 +5,18 @@ use brk_rmcp::transport::{ streamable_http_server::{StreamableHttpService, session::local::LocalSessionManager}, }; -mod api; -use api::*; use log::info; -use crate::AppState; +use crate::MCP; pub trait MCPRoutes { fn add_mcp_routes(self, interface: &'static Interface<'static>, mcp: bool) -> Self; } -impl MCPRoutes for Router { +impl MCPRoutes for Router +where + T: Clone + Send + Sync + 'static, +{ fn add_mcp_routes(self, interface: &'static Interface<'static>, mcp: bool) -> Self { if !mcp { return self; @@ -27,7 +28,7 @@ impl MCPRoutes for Router { }; let service = StreamableHttpService::new( - move || Ok(API::new(interface)), + move || Ok(MCP::new(interface)), LocalSessionManager::default().into(), config, ); diff --git a/crates/brk_parser/CHANGELOG.md b/crates/brk_parser/CHANGELOG.md deleted file mode 100644 index 9b9c5b195..000000000 --- a/crates/brk_parser/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -# v0.2.1 - -- Clean `.json` if necessary -- Only save `.json` if needed -- Updated benchmarks -- Updated packages - -# v0.2.0 - -- Removed the need for an output directory path -- Changed the location of the saved json file from the previously needed output directory path to the Bitcoin data directory -- Added a save of the json file every 144 * 30 blocks instead of only at the end diff --git a/crates/brk_parser/LICENSE.md b/crates/brk_parser/LICENSE.md deleted file mode 100644 index 3fd127e58..000000000 --- a/crates/brk_parser/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 biter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/crates/brk_server/Cargo.toml b/crates/brk_server/Cargo.toml index b7d800202..1e1cc3643 100644 --- a/crates/brk_server/Cargo.toml +++ b/crates/brk_server/Cargo.toml @@ -16,9 +16,10 @@ brk_core = { workspace = true } brk_exit = { workspace = true } brk_fetcher = { workspace = true } brk_indexer = { workspace = true } -brk_logger = { workspace = true } -brk_parser = { workspace = true } brk_interface = { workspace = true } +brk_logger = { workspace = true } +brk_mcp = { workspace = true } +brk_parser = { workspace = true } brk_vec = { workspace = true } clap = { workspace = true } clap_derive = { workspace = true } @@ -26,7 +27,6 @@ color-eyre = { workspace = true } jiff = { workspace = true } log = { workspace = true } minreq = { workspace = true } -brk_rmcp = { workspace = true } serde = { workspace = true } tokio = { workspace = true } tower-http = { version = "0.6.6", features = ["compression-full", "trace"] } diff --git a/crates/brk_server/src/api/interface/mod.rs b/crates/brk_server/src/api/interface/mod.rs index 7283be6ee..cf92afe3c 100644 --- a/crates/brk_server/src/api/interface/mod.rs +++ b/crates/brk_server/src/api/interface/mod.rs @@ -9,7 +9,7 @@ use brk_interface::{Format, Output, Params}; use brk_vec::{CollectableVec, StoredVec}; use color_eyre::eyre::eyre; -use crate::traits::{HeaderMapExtended, ModifiedState, ResponseExtended}; +use crate::traits::{HeaderMapExtended, ResponseExtended}; use super::AppState; @@ -63,24 +63,13 @@ fn req_to_response_res( return Err(eyre!("Request is too heavy, max weight is {MAX_WEIGHT}")); } - let mut date_modified_opt = None; + let etag = vecs.first().unwrap().1.etag(to); - if to.is_none() { - let not_modified = vecs - .iter() - .map(|(_, vec)| headers.check_if_modified_since_(vec.modified_time()?)) - .all(|res| { - res.ok().is_some_and(|(modified, date_modified)| { - if date_modified_opt.is_none_or(|dm| dm > date_modified) { - date_modified_opt.replace(date_modified); - } - modified == ModifiedState::NotModifiedSince - }) - }); - - if not_modified { - return Ok(Response::new_not_modified()); - } + if headers + .get_if_none_match() + .is_some_and(|prev_etag| etag == prev_etag) + { + return Ok(Response::new_not_modified()); } let output = interface.format(vecs, ¶ms.rest)?; @@ -100,9 +89,7 @@ fn req_to_response_res( headers.insert_cors(); - if let Some(date_modified) = date_modified_opt { - headers.insert_last_modified(date_modified); - } + headers.insert_etag(&etag); match format { Some(format) => { diff --git a/crates/brk_server/src/lib.rs b/crates/brk_server/src/lib.rs index b35a9ca0c..9e8a43671 100644 --- a/crates/brk_server/src/lib.rs +++ b/crates/brk_server/src/lib.rs @@ -24,6 +24,7 @@ use brk_computer::Computer; use brk_core::dot_brk_path; use brk_indexer::Indexer; use brk_interface::Interface; +use brk_mcp::route::MCPRoutes; use color_eyre::owo_colors::OwoColorize; use files::FilesRoutes; use log::{error, info}; @@ -32,11 +33,9 @@ use tower_http::{compression::CompressionLayer, trace::TraceLayer}; mod api; mod files; -mod mcp; mod traits; pub use files::Website; -use mcp::*; use tracing::Span; #[derive(Clone)] diff --git a/crates/brk_server/src/traits/header_map.rs b/crates/brk_server/src/traits/header_map.rs index 1cf0e5c7d..18992c830 100644 --- a/crates/brk_server/src/traits/header_map.rs +++ b/crates/brk_server/src/traits/header_map.rs @@ -5,7 +5,7 @@ use std::{ use axum::http::{ HeaderMap, - header::{self, IF_MODIFIED_SINCE}, + header::{self, IF_MODIFIED_SINCE, IF_NONE_MATCH}, }; use jiff::{Timestamp, civil::DateTime, fmt::strtime, tz::TimeZone}; use log::info; @@ -21,6 +21,8 @@ pub enum ModifiedState { pub trait HeaderMapExtended { fn insert_cors(&mut self); + fn get_if_none_match(&self) -> Option<&str>; + fn get_if_modified_since(&self) -> Option; fn check_if_modified_since(&self, path: &Path) -> color_eyre::Result<(ModifiedState, DateTime)>; @@ -31,6 +33,7 @@ pub trait HeaderMapExtended { fn insert_cache_control_must_revalidate(&mut self); fn insert_cache_control_immutable(&mut self); + fn insert_etag(&mut self, etag: &str); fn insert_last_modified(&mut self, date: DateTime); fn insert_content_disposition_attachment(&mut self); @@ -85,6 +88,10 @@ impl HeaderMapExtended for HeaderMap { self.insert(header::LAST_MODIFIED, formatted.parse().unwrap()); } + fn insert_etag(&mut self, etag: &str) { + self.insert(header::ETAG, etag.parse().unwrap()); + } + fn check_if_modified_since( &self, path: &Path, @@ -127,6 +134,10 @@ impl HeaderMapExtended for HeaderMap { None } + fn get_if_none_match(&self) -> Option<&str> { + self.get(IF_NONE_MATCH).and_then(|v| v.to_str().ok()) + } + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types fn insert_content_type(&mut self, path: &Path) { match path.extension().unwrap().to_str().unwrap() { diff --git a/crates/brk_state/Cargo.toml b/crates/brk_state/Cargo.toml index 4a2187cc6..fc30b22fd 100644 --- a/crates/brk_state/Cargo.toml +++ b/crates/brk_state/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brk_state" -description = "Various states used mainly by the computer" +description = "Various states used in the Bitcoin Research Kit" version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/brk_state/README.md b/crates/brk_state/README.md new file mode 100644 index 000000000..56e84e077 --- /dev/null +++ b/crates/brk_state/README.md @@ -0,0 +1,3 @@ +# BRK State + +Various states used in the Bitcoin Research Kit diff --git a/crates/brk_state/src/lib.rs b/crates/brk_state/src/lib.rs index 1145ace04..049eca714 100644 --- a/crates/brk_state/src/lib.rs +++ b/crates/brk_state/src/lib.rs @@ -1,3 +1,8 @@ +#![doc = include_str!("../README.md")] +// #![doc = "\n## Example\n\n```rust"] +// #![doc = include_str!("../examples/main.rs")] +// #![doc = "```"] + mod block; mod cohort; mod outputs; diff --git a/crates/brk_store/Cargo.toml b/crates/brk_store/Cargo.toml index 166f6884e..687831ee4 100644 --- a/crates/brk_store/Cargo.toml +++ b/crates/brk_store/Cargo.toml @@ -10,7 +10,6 @@ homepage.workspace = true repository.workspace = true [dependencies] -arc-swap = { workspace = true } brk_core = { workspace = true } byteview = { workspace = true } fjall = { workspace = true } diff --git a/crates/brk_vec/src/traits/any.rs b/crates/brk_vec/src/traits/any.rs index 3288abee5..e9d35c1e2 100644 --- a/crates/brk_vec/src/traits/any.rs +++ b/crates/brk_vec/src/traits/any.rs @@ -1,6 +1,4 @@ -use std::time::Duration; - -use brk_core::{Result, Version}; +use brk_core::Version; use super::{BoxedVecIterator, StoredIndex, StoredType}; @@ -11,9 +9,23 @@ pub trait AnyVec: Send + Sync { fn is_empty(&self) -> bool { self.len() == 0 } - fn modified_time(&self) -> Result; fn index_type_to_string(&self) -> &'static str; fn value_type_to_size_of(&self) -> usize; + fn etag(&self, to: Option) -> String { + let len = self.len(); + format!( + "{}-{:?}", + to.map_or(len, |to| { + if to.is_negative() { + len.checked_sub(to.unsigned_abs() as usize) + .unwrap_or_default() + } else { + to as usize + } + }), + self.version() + ) + } } pub trait AnyIterableVec: AnyVec { diff --git a/crates/brk_vec/src/traits/generic.rs b/crates/brk_vec/src/traits/generic.rs index 6232c44ca..5e7ae4679 100644 --- a/crates/brk_vec/src/traits/generic.rs +++ b/crates/brk_vec/src/traits/generic.rs @@ -3,7 +3,6 @@ use std::{ io::{self, Seek, SeekFrom, Write}, path::{Path, PathBuf}, sync::Arc, - time::{self, Duration}, }; use arc_swap::ArcSwap; @@ -168,12 +167,4 @@ where fn flush(&mut self) -> Result<()>; fn truncate_if_needed(&mut self, index: I) -> Result<()>; - - fn modified_time_(&self) -> Result { - Ok(self - .file() - .metadata()? - .modified()? - .duration_since(time::UNIX_EPOCH)?) - } } diff --git a/crates/brk_vec/src/variants/compressed.rs b/crates/brk_vec/src/variants/compressed.rs index d0c76ed6a..98a9f366d 100644 --- a/crates/brk_vec/src/variants/compressed.rs +++ b/crates/brk_vec/src/variants/compressed.rs @@ -3,7 +3,6 @@ use std::{ mem, path::{Path, PathBuf}, sync::Arc, - time::Duration, }; use arc_swap::{ArcSwap, Guard}; @@ -381,11 +380,6 @@ where self.len_() } - #[inline] - fn modified_time(&self) -> Result { - self.modified_time_() - } - #[inline] fn index_type_to_string(&self) -> &'static str { I::to_string() diff --git a/crates/brk_vec/src/variants/computed.rs b/crates/brk_vec/src/variants/computed.rs index 0c838eb2d..aefca73b8 100644 --- a/crates/brk_vec/src/variants/computed.rs +++ b/crates/brk_vec/src/variants/computed.rs @@ -1,4 +1,4 @@ -use std::{fs, path::Path, time::Duration}; +use std::{fs, path::Path}; use brk_exit::Exit; use clap_derive::ValueEnum; @@ -245,15 +245,6 @@ where } } - fn modified_time(&self) -> Result { - match self { - ComputedVec::Eager { vec, .. } => vec.modified_time(), - ComputedVec::LazyFrom1(v) => v.modified_time(), - ComputedVec::LazyFrom2(v) => v.modified_time(), - ComputedVec::LazyFrom3(v) => v.modified_time(), - } - } - #[inline] fn value_type_to_size_of(&self) -> usize { size_of::() diff --git a/crates/brk_vec/src/variants/eager.rs b/crates/brk_vec/src/variants/eager.rs index 0c621843d..d684403d7 100644 --- a/crates/brk_vec/src/variants/eager.rs +++ b/crates/brk_vec/src/variants/eager.rs @@ -5,7 +5,6 @@ use std::{ fmt::Debug, ops::{Add, Div, Mul}, path::{Path, PathBuf}, - time::Duration, }; use arc_swap::ArcSwap; @@ -1304,11 +1303,6 @@ where self.0.len() } - #[inline] - fn modified_time(&self) -> Result { - self.0.modified_time() - } - #[inline] fn index_type_to_string(&self) -> &'static str { I::to_string() diff --git a/crates/brk_vec/src/variants/indexed.rs b/crates/brk_vec/src/variants/indexed.rs index 99436dcf2..460712b6b 100644 --- a/crates/brk_vec/src/variants/indexed.rs +++ b/crates/brk_vec/src/variants/indexed.rs @@ -1,4 +1,4 @@ -use std::{cmp::Ordering, fmt::Debug, path::Path, time::Duration}; +use std::{cmp::Ordering, fmt::Debug, path::Path}; use arc_swap::ArcSwap; use brk_core::{Error, Height, Result, Value, Version}; @@ -103,11 +103,6 @@ where self.0.len() } - #[inline] - fn modified_time(&self) -> Result { - self.0.modified_time() - } - #[inline] fn index_type_to_string(&self) -> &'static str { I::to_string() diff --git a/crates/brk_vec/src/variants/lazy1.rs b/crates/brk_vec/src/variants/lazy1.rs index 3d42edc2e..b55bef61c 100644 --- a/crates/brk_vec/src/variants/lazy1.rs +++ b/crates/brk_vec/src/variants/lazy1.rs @@ -143,10 +143,6 @@ where self.source.len() } - fn modified_time(&self) -> Result { - self.source.modified_time() - } - #[inline] fn value_type_to_size_of(&self) -> usize { size_of::() diff --git a/crates/brk_vec/src/variants/lazy2.rs b/crates/brk_vec/src/variants/lazy2.rs index ea36216f5..2a244d061 100644 --- a/crates/brk_vec/src/variants/lazy2.rs +++ b/crates/brk_vec/src/variants/lazy2.rs @@ -188,13 +188,6 @@ where len1.min(len2) } - fn modified_time(&self) -> Result { - Ok(self - .source1 - .modified_time()? - .min(self.source2.modified_time()?)) - } - #[inline] fn value_type_to_size_of(&self) -> usize { size_of::() diff --git a/crates/brk_vec/src/variants/lazy3.rs b/crates/brk_vec/src/variants/lazy3.rs index 19f4cf794..c9a351fa0 100644 --- a/crates/brk_vec/src/variants/lazy3.rs +++ b/crates/brk_vec/src/variants/lazy3.rs @@ -222,14 +222,6 @@ where len1.min(len2).min(len3) } - fn modified_time(&self) -> Result { - Ok(self - .source1 - .modified_time()? - .min(self.source2.modified_time()?) - .min(self.source3.modified_time()?)) - } - #[inline] fn value_type_to_size_of(&self) -> usize { size_of::() diff --git a/crates/brk_vec/src/variants/raw.rs b/crates/brk_vec/src/variants/raw.rs index afe59af3a..4319c8c57 100644 --- a/crates/brk_vec/src/variants/raw.rs +++ b/crates/brk_vec/src/variants/raw.rs @@ -5,7 +5,6 @@ use std::{ mem, path::{Path, PathBuf}, sync::Arc, - time::Duration, }; use arc_swap::{ArcSwap, Guard}; @@ -250,11 +249,6 @@ where self.len_() } - #[inline] - fn modified_time(&self) -> Result { - self.modified_time_() - } - #[inline] fn index_type_to_string(&self) -> &'static str { I::to_string() diff --git a/crates/brk_vec/src/variants/stored.rs b/crates/brk_vec/src/variants/stored.rs index 20874aabb..a4cccb050 100644 --- a/crates/brk_vec/src/variants/stored.rs +++ b/crates/brk_vec/src/variants/stored.rs @@ -1,7 +1,6 @@ use std::{ fs::File, path::{Path, PathBuf}, - time::Duration, }; use arc_swap::ArcSwap; @@ -191,14 +190,6 @@ where self.pushed_len() + self.stored_len() } - #[inline] - fn modified_time(&self) -> Result { - match self { - StoredVec::Raw(v) => v.modified_time(), - StoredVec::Compressed(v) => v.modified_time(), - } - } - fn name(&self) -> &str { match self { StoredVec::Raw(v) => v.name(), diff --git a/websites/default/scripts/main.js b/websites/default/scripts/main.js index c8d022cd8..6da40699c 100644 --- a/websites/default/scripts/main.js +++ b/websites/default/scripts/main.js @@ -951,10 +951,7 @@ function createUtils() { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "Years"; } - if ( - (!unit || thoroughUnitCheck) && - (id === "0" || id === "1" || id === "50" || id === "100") - ) { + if ((!unit || thoroughUnitCheck) && id.startsWith("constant")) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "constant"; } @@ -2226,7 +2223,6 @@ function main() { import("./table.js").then(({ init }) => signals.runWithOwner(owner, () => init({ - colors, elements, signals, utils, diff --git a/websites/default/scripts/options.js b/websites/default/scripts/options.js index 16e94f5a4..94feb8e54 100644 --- a/websites/default/scripts/options.js +++ b/websites/default/scripts/options.js @@ -3484,7 +3484,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) { } } else { const { input, label } = utils.dom.createLabeledInput({ - inputId: `${option.id}_${frame}${id || ""}_selector`, + inputId: `${option.id}-${frame}${id || ""}-selector`, inputValue: option.id, inputName: `option_${frame}${id || ""}`, labelTitle: option.title, @@ -3667,7 +3667,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) { } else if ("url" in anyPartial) { option = /** @satisfies {UrlOption} */ ({ kind: "url", - id: `${utils.stringToId(anyPartial.name)}_url`, + id: `${utils.stringToId(anyPartial.name)}-url`, name: anyPartial.name, path: path || [], title: anyPartial.name, @@ -3676,7 +3676,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) { }); } else { const title = anyPartial.title || anyPartial.name; - const id = `chart_${utils.stringToId(title)}`; + const id = `chart-${utils.stringToId(title)}`; option = /** @satisfies {ChartOption} */ ({ kind: "chart", id, diff --git a/websites/default/scripts/simulation.js b/websites/default/scripts/simulation.js index f003e9031..4f6864f27 100644 --- a/websites/default/scripts/simulation.js +++ b/websites/default/scripts/simulation.js @@ -268,7 +268,7 @@ export function init({ /** @type {Record} */ const idToFrequency = {}; - list.forEach((anyFreq, index) => { + list.forEach((anyFreq) => { if ("list" in anyFreq) { anyFreq.list?.forEach((freq) => { idToFrequency[freq.value] = freq; diff --git a/websites/default/scripts/table.js b/websites/default/scripts/table.js index 2d876bcc5..a7888a630 100644 --- a/websites/default/scripts/table.js +++ b/websites/default/scripts/table.js @@ -353,7 +353,6 @@ function createTable({ /** * @param {Object} args - * @param {Colors} args.colors * @param {Signals} args.signals * @param {Utilities} args.utils * @param {Option} args.option @@ -362,7 +361,6 @@ function createTable({ * @param {VecIdToIndexes} args.vecIdToIndexes */ export function init({ - colors, elements, signals, option, @@ -500,7 +498,7 @@ function createIndexToVecIds(vecIdToIndexes) { }); return arr; }, - /** @type {VecId[][]} */ (new Array(24)), + /** @type {VecId[][]} */ (Array.from({ length: 24 })), ); indexToVecIds.forEach((arr) => { arr.sort();