diff --git a/Cargo.lock b/Cargo.lock index 704b0e933..d39e5d009 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -527,7 +527,6 @@ dependencies = [ name = "brk_computer" version = "0.0.83" dependencies = [ - "bincode", "bitcoin", "bitcoincore-rpc", "brk_core", @@ -550,7 +549,6 @@ dependencies = [ name = "brk_core" version = "0.0.83" dependencies = [ - "bincode", "bitcoin", "bitcoincore-rpc", "byteview", @@ -617,7 +615,6 @@ dependencies = [ "brk_vecs", "color-eyre", "derive_deref", - "rmcp", "schemars 1.0.4", "serde", "serde_json", @@ -641,8 +638,8 @@ version = "0.0.83" dependencies = [ "axum", "brk_interface", + "brk_rmcp", "log", - "rmcp", ] [[package]] @@ -660,6 +657,49 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "brk_rmcp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47aa1e268ee1def8f5c8680a0b178235c0c00cb573bd1c17bc5788873c8f658c" +dependencies = [ + "base64 0.22.1", + "brk_rmcp-macros", + "bytes", + "chrono", + "futures", + "http", + "http-body", + "http-body-util", + "paste", + "pin-project-lite", + "rand 0.9.2", + "schemars 1.0.4", + "serde", + "serde_json", + "sse-stream", + "thiserror 2.0.12", + "tokio", + "tokio-stream", + "tokio-util", + "tower-service", + "tracing", + "uuid", +] + +[[package]] +name = "brk_rmcp-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2160476036639cdb3657939886955ba603ef42d93f07735c944ae41eec6cbc" +dependencies = [ + "darling 0.21.0", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.104", +] + [[package]] name = "brk_rolldown" version = "0.1.1" @@ -1591,9 +1631,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" @@ -2323,9 +2363,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" +checksum = "360e552c93fa0e8152ab463bc4c4837fce76a225df11dfaeea66c313de5e61f7" dependencies = [ "bitflags 2.9.1", "libc", @@ -2633,9 +2673,9 @@ dependencies = [ [[package]] name = "oxc-browserslist" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20605046d78dbba8ed6c1c10b5ee21a83d265825943bce8bc40d17b4c48d5aca" +checksum = "509ae58826553dbd720886b6a77e7bb2a953d28a52728a74cc1fe296d66fa9a2" dependencies = [ "bincode", "nom", @@ -2648,9 +2688,9 @@ dependencies = [ [[package]] name = "oxc-miette" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00cb1a49ec377f62606cbf047794efd37d668dbcbcefaeb5bf43f89b3c391418" +checksum = "e8f905f1293ce969f8b6f08f2f4e8a0fbfd26dec42a30ea98b436d2faf01f50f" dependencies = [ "cfg-if", "owo-colors", @@ -2662,9 +2702,9 @@ dependencies = [ [[package]] name = "oxc-miette-derive" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1739910e9871fe8d6e311f80fb2793756335aec97b0f985e778cbf4bc5cf574f" +checksum = "7cd092b10278cef8cc76dad34116988c2f0ca34bf9082de5513bacd95f4553d0" dependencies = [ "proc-macro2", "quote", @@ -3475,9 +3515,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.15" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags 2.9.1", ] @@ -3579,49 +3619,6 @@ dependencies = [ "libc", ] -[[package]] -name = "rmcp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b008b927a85d514699ff304be84c5084598596e6cad4a6f5bc67207715fafe5f" -dependencies = [ - "base64 0.22.1", - "bytes", - "chrono", - "futures", - "http", - "http-body", - "http-body-util", - "paste", - "pin-project-lite", - "rand 0.9.2", - "rmcp-macros", - "schemars 1.0.4", - "serde", - "serde_json", - "sse-stream", - "thiserror 2.0.12", - "tokio", - "tokio-stream", - "tokio-util", - "tower-service", - "tracing", - "uuid", -] - -[[package]] -name = "rmcp-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7465280d5f73f2c5c99017a04af407b2262455a149f255ad22f2b0b29087695c" -dependencies = [ - "darling 0.21.0", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.104", -] - [[package]] name = "rolldown-ariadne" version = "0.5.2" @@ -3644,9 +3641,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -3993,12 +3990,12 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.5.10" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4226,9 +4223,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.46.1" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" dependencies = [ "backtrace", "bytes", @@ -4239,7 +4236,7 @@ dependencies = [ "slab", "socket2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4279,9 +4276,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac" +checksum = "e06723639aaded957e5a80be250c1f82f274b9d23ebb4d94163668470623461c" dependencies = [ "indexmap 2.10.0", "serde", @@ -4835,7 +4832,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -4856,10 +4853,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", diff --git a/Cargo.toml b/Cargo.toml index c87776ba3..f2a0d330a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ inherits = "release" [workspace.dependencies] axum = "0.8.4" -bincode = { version = "2.0.1", features = ["serde"] } bitcoin = { version = "0.32.6", features = ["serde"] } bitcoincore-rpc = "0.19.0" brk_bundler = { version = "0.0.83", path = "crates/brk_bundler" } @@ -47,22 +46,15 @@ color-eyre = "0.6.5" derive_deref = "1.1.1" fjall = "2.11.2" jiff = "0.2.15" -libc = "0.2.174" log = { version = "0.4.27" } minreq = { version = "2.14.0", features = ["https", "serde_json"] } parking_lot = "0.12.4" rayon = "1.10.0" -rmcp = { version = "0.3.0", features = [ - "transport-worker", - "transport-streamable-http-server", -] } -schemars = "1.0.4" serde = { version = "1.0.219" } serde_bytes = "0.11.17" serde_derive = "1.0.219" serde_json = { version = "1.0.141", features = ["float_roundtrip"] } -tabled = "0.20.0" -tokio = { version = "1.46.1", features = ["rt-multi-thread"] } +tokio = { version = "1.47.0", features = ["rt-multi-thread"] } zerocopy = { version = "0.8.26" } zerocopy-derive = "0.8.26" diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 3f2b959e6..3f7a68ec1 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -24,7 +24,7 @@ color-eyre = { workspace = true } log = { workspace = true } serde = { workspace = true } tokio = { workspace = true } -toml = "0.9.2" +toml = "0.9.3" [[bin]] name = "brk" diff --git a/crates/brk_computer/Cargo.toml b/crates/brk_computer/Cargo.toml index 674bea46a..0eabffa43 100644 --- a/crates/brk_computer/Cargo.toml +++ b/crates/brk_computer/Cargo.toml @@ -8,7 +8,6 @@ homepage.workspace = true repository.workspace = true [dependencies] -bincode = { workspace = true } bitcoin = { workspace = true } bitcoincore-rpc = { workspace = true } brk_core = { workspace = true } diff --git a/crates/brk_computer/src/states/price_to_amount.rs b/crates/brk_computer/src/states/price_to_amount.rs index 8d6d0b8bc..72eb9efe0 100644 --- a/crates/brk_computer/src/states/price_to_amount.rs +++ b/crates/brk_computer/src/states/price_to_amount.rs @@ -1,14 +1,14 @@ use std::{ collections::BTreeMap, - fs::{self, File}, - io::{BufReader, BufWriter}, + fs, + io::{Cursor, Read}, path::{Path, PathBuf}, }; -use bincode::{Decode, Encode, config, decode_from_std_read, encode_into_std_write}; -use brk_core::{Dollars, Height, Result, Sats}; +use brk_core::{Dollars, Error, Height, Result, Sats}; use derive_deref::{Deref, DerefMut}; use serde::{Deserialize, Serialize}; +use zerocopy::{FromBytes, IntoBytes}; use crate::states::SupplyState; @@ -19,9 +19,6 @@ pub struct PriceToAmount { state: State, } -#[derive(Clone, Default, Debug, Deref, DerefMut, Serialize, Deserialize, Encode, Decode)] -struct State(BTreeMap); - impl PriceToAmount { pub fn forced_import(path: &Path, name: &str) -> Self { Self::import(path, name).unwrap_or_else(|_| Self { @@ -35,10 +32,7 @@ impl PriceToAmount { let path = Self::path_(path, name); fs::create_dir_all(&path)?; - let config = config::standard(); - let file = File::open(Self::path_state_(&path))?; - let mut reader = BufReader::new(file); - let state = decode_from_std_read(&mut reader, config)?; + let state = State::deserialize(&fs::read(&path)?)?; Ok(Self { height: Height::try_from(Self::path_height_(&path).as_path()).ok(), @@ -86,13 +80,7 @@ impl PriceToAmount { pub fn flush(&mut self, height: Height) -> Result<()> { self.height = Some(height); height.write(&self.path_height())?; - - let file = File::create(self.path_state()).inspect_err(|_| { - dbg!(self.path_state()); - })?; - let mut writer = BufWriter::new(file); - encode_into_std_write(&self.state, &mut writer, config::standard())?; - + fs::write(self.path_state(), self.state.serialize())?; Ok(()) } @@ -118,3 +106,47 @@ impl PriceToAmount { path.join("height") } } + +#[derive(Clone, Default, Debug, Deref, DerefMut, Serialize, Deserialize)] +struct State(BTreeMap); + +impl State { + fn serialize(&self) -> Vec { + let len = self.len(); + + let mut buffer = Vec::with_capacity(8 + len * 16); + + buffer.extend_from_slice(len.as_bytes()); + + self.iter().for_each(|(key, value)| { + buffer.extend_from_slice(key.as_bytes()); + buffer.extend_from_slice(value.as_bytes()); + }); + + buffer + } + + fn deserialize(data: &[u8]) -> Result { + let mut cursor = Cursor::new(data); + let mut buffer = [0u8; 8]; + + cursor + .read_exact(&mut buffer) + .map_err(|_| Error::Str("Failed to read entry count"))?; + let entry_count = usize::read_from_bytes(&buffer)?; + + let mut map = BTreeMap::new(); + + for _ in 0..entry_count { + cursor.read_exact(&mut buffer)?; + let key = Dollars::read_from_bytes(&buffer)?; + + cursor.read_exact(&mut buffer)?; + let value = Sats::read_from_bytes(&buffer)?; + + map.insert(key, value); + } + + Ok(Self(map)) + } +} diff --git a/crates/brk_core/Cargo.toml b/crates/brk_core/Cargo.toml index 41d099fd0..3532fdd13 100644 --- a/crates/brk_core/Cargo.toml +++ b/crates/brk_core/Cargo.toml @@ -8,7 +8,6 @@ homepage.workspace = true repository.workspace = true [dependencies] -bincode = { workspace = true } bitcoin = { workspace = true } bitcoincore-rpc = { workspace = true } byteview = { workspace = true } diff --git a/crates/brk_core/src/error.rs b/crates/brk_core/src/error.rs index 106718f52..7a158c7bb 100644 --- a/crates/brk_core/src/error.rs +++ b/crates/brk_core/src/error.rs @@ -15,8 +15,6 @@ pub enum Error { Fjall(fjall::Error), SystemTimeError(time::SystemTimeError), ZeroCopyError, - BincodeEncodeError(bincode::error::EncodeError), - BincodeDecodeError(bincode::error::DecodeError), WrongEndian, DifferentVersion { found: Version, expected: Version }, @@ -81,18 +79,6 @@ impl From for Error { } } -impl From for Error { - fn from(error: bincode::error::DecodeError) -> Self { - Self::BincodeDecodeError(error) - } -} - -impl From for Error { - fn from(error: bincode::error::EncodeError) -> Self { - Self::BincodeEncodeError(error) - } -} - impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -101,8 +87,6 @@ impl fmt::Display for Error { Error::SerdeJson(error) => Debug::fmt(&error, f), Error::Jiff(error) => Debug::fmt(&error, f), Error::Fjall(error) => Debug::fmt(&error, f), - Error::BincodeDecodeError(error) => Debug::fmt(&error, f), - Error::BincodeEncodeError(error) => Debug::fmt(&error, f), Error::ZeroCopyError => write!(f, "ZeroCopy error"), Error::UnexpectedData => write!(f, "Unexpected data"), diff --git a/crates/brk_core/src/structs/dollars.rs b/crates/brk_core/src/structs/dollars.rs index 6b3a20d19..d88b2b1f9 100644 --- a/crates/brk_core/src/structs/dollars.rs +++ b/crates/brk_core/src/structs/dollars.rs @@ -4,13 +4,11 @@ use std::{ ops::{Add, AddAssign, Div, Mul}, }; -use bincode::{Decode, Encode}; -use byteview::ByteView; use derive_deref::Deref; use serde::{Deserialize, Serialize}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; -use crate::{CheckedSub, copy_first_8bytes}; +use crate::CheckedSub; use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64}; @@ -26,8 +24,6 @@ use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64}; KnownLayout, Serialize, Deserialize, - Encode, - Decode, )] pub struct Dollars(f64); @@ -362,22 +358,3 @@ impl Ord for Dollars { } } } - -impl From for Dollars { - fn from(value: ByteView) -> Self { - let bytes = copy_first_8bytes(&value).unwrap(); - Self::from(f64::from_be_bytes(bytes)) - } -} - -impl From for ByteView { - fn from(value: Dollars) -> Self { - Self::from(&value) - } -} - -impl From<&Dollars> for ByteView { - fn from(value: &Dollars) -> Self { - Self::new(&value.to_be_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2aaddressindex.rs b/crates/brk_core/src/structs/p2aaddressindex.rs index 6c98a44a3..53fa4ce6a 100644 --- a/crates/brk_core/src/structs/p2aaddressindex.rs +++ b/crates/brk_core/src/structs/p2aaddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -76,19 +74,3 @@ impl Printable for P2AAddressIndex { &["aaddr", "p2aaddr", "p2aaddressindex"] } } - -impl From for P2AAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2AAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2AAddressIndex> for ByteView { - fn from(value: &P2AAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2pk33addressindex.rs b/crates/brk_core/src/structs/p2pk33addressindex.rs index c6f5aa7de..c15ce1a17 100644 --- a/crates/brk_core/src/structs/p2pk33addressindex.rs +++ b/crates/brk_core/src/structs/p2pk33addressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2PK33AddressIndex { &["pk33addr", "p2pk33addr", "p2pk33addressindex"] } } - -impl From for P2PK33AddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2PK33AddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2PK33AddressIndex> for ByteView { - fn from(value: &P2PK33AddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2pk65addressindex.rs b/crates/brk_core/src/structs/p2pk65addressindex.rs index 8de0a1df0..a5abb8654 100644 --- a/crates/brk_core/src/structs/p2pk65addressindex.rs +++ b/crates/brk_core/src/structs/p2pk65addressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -76,19 +74,3 @@ impl Printable for P2PK65AddressIndex { &["pk65addr", "p2pk65addr", "p2pk65addressindex"] } } - -impl From for P2PK65AddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2PK65AddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2PK65AddressIndex> for ByteView { - fn from(value: &P2PK65AddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2pkhaddressindex.rs b/crates/brk_core/src/structs/p2pkhaddressindex.rs index a481af106..32c8c074f 100644 --- a/crates/brk_core/src/structs/p2pkhaddressindex.rs +++ b/crates/brk_core/src/structs/p2pkhaddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2PKHAddressIndex { &["pkhaddr", "p2pkhaddr", "p2pkhaddressindex"] } } - -impl From for P2PKHAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2PKHAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2PKHAddressIndex> for ByteView { - fn from(value: &P2PKHAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2shaddressindex.rs b/crates/brk_core/src/structs/p2shaddressindex.rs index 4ee432881..95aa9c09f 100644 --- a/crates/brk_core/src/structs/p2shaddressindex.rs +++ b/crates/brk_core/src/structs/p2shaddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2SHAddressIndex { &["shaddr", "p2shaddr", "p2shaddressindex"] } } - -impl From for P2SHAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2SHAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2SHAddressIndex> for ByteView { - fn from(value: &P2SHAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2traddressindex.rs b/crates/brk_core/src/structs/p2traddressindex.rs index 7f76cb713..d9ab27c2f 100644 --- a/crates/brk_core/src/structs/p2traddressindex.rs +++ b/crates/brk_core/src/structs/p2traddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2TRAddressIndex { &["traddr", "p2traddr", "p2traddressindex"] } } - -impl From for P2TRAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2TRAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2TRAddressIndex> for ByteView { - fn from(value: &P2TRAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2wpkhaddressindex.rs b/crates/brk_core/src/structs/p2wpkhaddressindex.rs index dbda26d63..6a21f1b44 100644 --- a/crates/brk_core/src/structs/p2wpkhaddressindex.rs +++ b/crates/brk_core/src/structs/p2wpkhaddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2WPKHAddressIndex { &["wpkhaddr", "p2wpkhaddr", "p2wpkhaddressindex"] } } - -impl From for P2WPKHAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2WPKHAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2WPKHAddressIndex> for ByteView { - fn from(value: &P2WPKHAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/p2wshaddressindex.rs b/crates/brk_core/src/structs/p2wshaddressindex.rs index 3d92cd598..3256d0806 100644 --- a/crates/brk_core/src/structs/p2wshaddressindex.rs +++ b/crates/brk_core/src/structs/p2wshaddressindex.rs @@ -1,9 +1,7 @@ use std::ops::Add; -use byteview::ByteView; use derive_deref::{Deref, DerefMut}; use serde::Serialize; -use zerocopy::{FromBytes, IntoBytes}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{CheckedSub, Printable, TypeIndex}; @@ -77,19 +75,3 @@ impl Printable for P2WSHAddressIndex { &["wshaddr", "p2wshaddr", "p2wshaddressindex"] } } - -impl From for P2WSHAddressIndex { - fn from(value: ByteView) -> Self { - Self::read_from_bytes(&value).unwrap() - } -} -impl From for ByteView { - fn from(value: P2WSHAddressIndex) -> Self { - Self::from(&value) - } -} -impl From<&P2WSHAddressIndex> for ByteView { - fn from(value: &P2WSHAddressIndex) -> Self { - Self::new(value.as_bytes()) - } -} diff --git a/crates/brk_core/src/structs/sats.rs b/crates/brk_core/src/structs/sats.rs index 81c00d7ea..2ff58fdd1 100644 --- a/crates/brk_core/src/structs/sats.rs +++ b/crates/brk_core/src/structs/sats.rs @@ -3,13 +3,12 @@ use std::{ ops::{Add, AddAssign, Div, Mul, SubAssign}, }; -use bincode::{Decode, Encode}; use bitcoin::Amount; -use byteview::ByteView; +use derive_deref::Deref; use serde::{Deserialize, Serialize}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; -use crate::{CheckedSub, StoredF64, copy_first_8bytes}; +use crate::{CheckedSub, StoredF64}; use super::{Bitcoin, Cents, Dollars, Height}; @@ -21,6 +20,7 @@ use super::{Bitcoin, Cents, Dollars, Height}; Ord, Clone, Copy, + Deref, Default, FromBytes, Immutable, @@ -28,8 +28,6 @@ use super::{Bitcoin, Cents, Dollars, Height}; KnownLayout, Serialize, Deserialize, - Encode, - Decode, )] pub struct Sats(u64); @@ -243,25 +241,6 @@ impl From for u128 { } } -impl From for Sats { - fn from(value: ByteView) -> Self { - let bytes = copy_first_8bytes(&value).unwrap(); - Self::from(u64::from_be_bytes(bytes)) - } -} - -impl From<&Sats> for ByteView { - fn from(value: &Sats) -> Self { - Self::new(&value.0.to_be_bytes()) - } -} - -impl From for ByteView { - fn from(value: Sats) -> Self { - Self::from(&value) - } -} - impl Mul for usize { type Output = Sats; fn mul(self, rhs: Sats) -> Self::Output { diff --git a/crates/brk_core/src/structs/typeindex_with_outputindex.rs b/crates/brk_core/src/structs/typeindex_with_outputindex.rs index 8a80a1dfd..8db54e167 100644 --- a/crates/brk_core/src/structs/typeindex_with_outputindex.rs +++ b/crates/brk_core/src/structs/typeindex_with_outputindex.rs @@ -30,6 +30,7 @@ impl From for TypeIndexWithOutputindex { } } } + impl From for ByteView { fn from(value: TypeIndexWithOutputindex) -> Self { ByteView::from(&value) diff --git a/crates/brk_indexer/examples/indexer.rs b/crates/brk_indexer/examples/indexer.rs index 9e1fcdf29..f92927776 100644 --- a/crates/brk_indexer/examples/indexer.rs +++ b/crates/brk_indexer/examples/indexer.rs @@ -14,10 +14,12 @@ fn main() -> color_eyre::Result<()> { brk_logger::init(Some(Path::new(".log"))); - // let bitcoin_dir = brk_core::default_bitcoin_path(); - let bitcoin_dir = Path::new("/Volumes/WD_BLACK1/bitcoin"); + let bitcoin_dir = brk_core::default_bitcoin_path(); + // let bitcoin_dir = Path::new("/Volumes/WD_BLACK1/bitcoin"); + let outputs_dir = Path::new("./_outputs"); + fs::create_dir_all(outputs_dir)?; // let outputs_dir = brk_core::default_brk_path().join("outputs"); - let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk"); + // let outputs_dir = Path::new("/Volumes/WD_BLACK1/brk"); let rpc = Box::leak(Box::new(bitcoincore_rpc::Client::new( "http://localhost:8332", diff --git a/crates/brk_interface/Cargo.toml b/crates/brk_interface/Cargo.toml index acdf1927c..c1c52f07b 100644 --- a/crates/brk_interface/Cargo.toml +++ b/crates/brk_interface/Cargo.toml @@ -14,9 +14,8 @@ brk_indexer = { workspace = true } brk_vecs = { workspace = true } color-eyre = { workspace = true } derive_deref = { workspace = true } -rmcp = { workspace = true } -schemars = { workspace = true } +schemars = "1.0.4" serde = { workspace = true } serde_json = { workspace = true } serde_with = "3.14.0" -tabled = { workspace = true } +tabled = "0.20.0" diff --git a/crates/brk_interface/src/format.rs b/crates/brk_interface/src/format.rs index 6f75cb719..0e7445e4c 100644 --- a/crates/brk_interface/src/format.rs +++ b/crates/brk_interface/src/format.rs @@ -1,5 +1,5 @@ use color_eyre::eyre::eyre; -use rmcp::schemars::JsonSchema; +use schemars::JsonSchema; use serde::Deserialize; #[allow(clippy::upper_case_acronyms)] diff --git a/crates/brk_interface/src/params.rs b/crates/brk_interface/src/params.rs index d4291786e..6bbdef73d 100644 --- a/crates/brk_interface/src/params.rs +++ b/crates/brk_interface/src/params.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use rmcp::schemars::{self, JsonSchema}; +use schemars::JsonSchema; use serde::Deserialize; use crate::{ diff --git a/crates/brk_mcp/Cargo.toml b/crates/brk_mcp/Cargo.toml index bce4ad5f6..3b8c450e7 100644 --- a/crates/brk_mcp/Cargo.toml +++ b/crates/brk_mcp/Cargo.toml @@ -11,4 +11,7 @@ repository.workspace = true axum = { workspace = true } brk_interface = { workspace = true } log = { workspace = true } -rmcp = { workspace = true } +brk_rmcp = { version = "0.3.0", features = [ + "transport-worker", + "transport-streamable-http-server", +] } diff --git a/crates/brk_mcp/src/lib.rs b/crates/brk_mcp/src/lib.rs index fa77063c9..c8fc47bd2 100644 --- a/crates/brk_mcp/src/lib.rs +++ b/crates/brk_mcp/src/lib.rs @@ -4,14 +4,14 @@ // #![doc = "```"] use brk_interface::{IdParam, Interface, PaginatedIndexParam, PaginationParam, Params}; -use log::info; -use rmcp::{ +use brk_rmcp::{ ErrorData as McpError, RoleServer, ServerHandler, handler::server::{router::tool::ToolRouter, tool::Parameters}, model::*, service::RequestContext, tool, tool_handler, tool_router, }; +use log::info; pub mod route; diff --git a/crates/brk_mcp/src/route.rs b/crates/brk_mcp/src/route.rs index de51dfd75..9e17b9cac 100644 --- a/crates/brk_mcp/src/route.rs +++ b/crates/brk_mcp/src/route.rs @@ -1,6 +1,6 @@ use axum::Router; use brk_interface::Interface; -use rmcp::transport::{ +use brk_rmcp::transport::{ StreamableHttpServerConfig, streamable_http_server::{StreamableHttpService, session::local::LocalSessionManager}, }; diff --git a/crates/brk_store/examples/main.rs b/crates/brk_store/examples/main.rs index 82400ecdd..9d216384a 100644 --- a/crates/brk_store/examples/main.rs +++ b/crates/brk_store/examples/main.rs @@ -1,21 +1,20 @@ use std::path::Path; -use brk_core::{Dollars, Height, Result, Sats, Version}; -use brk_store::{AnyStore, Store}; +use brk_core::Result; fn main() -> Result<()> { let p = Path::new("./examples/_fjall"); let keyspace = brk_store::open_keyspace(p)?; - let mut store: Store = - brk_store::Store::import(&keyspace, p, "n", Version::ZERO, None)?; + // let mut store: Store = + // brk_store::Store::import(&keyspace, p, "n", Version::ZERO, None)?; - store.insert_if_needed(Dollars::from(10.0), Sats::FIFTY_BTC, Height::ZERO); + // store.insert_if_needed(Sats::new(10), Sats::FIFTY_BTC, Height::ZERO); - store.commit(Height::ZERO)?; + // store.commit(Height::ZERO)?; - store.persist()?; + // store.persist()?; Ok(()) } diff --git a/crates/brk_vecs/src/file/layout.rs b/crates/brk_vecs/src/file/layout.rs index 7da1a2e16..5bef90b0b 100644 --- a/crates/brk_vecs/src/file/layout.rs +++ b/crates/brk_vecs/src/file/layout.rs @@ -9,6 +9,7 @@ use super::{Region, Regions}; pub struct Layout { start_to_index: BTreeMap, start_to_hole: BTreeMap, + start_to_reserved: BTreeMap, } impl From<&Regions> for Layout { @@ -43,6 +44,7 @@ impl From<&Regions> for Layout { Self { start_to_index, start_to_hole, + start_to_reserved: BTreeMap::default(), } } } @@ -56,28 +58,73 @@ impl Layout { &self.start_to_hole } - pub fn get_last_region(&self) -> Option<(u64, usize)> { - self.start_to_index - .last_key_value() - .map(|(start, index)| (*start, *index)) + pub fn len(&self, regions: &Regions) -> u64 { + let mut len = 0; + let mut start = 0; + if let Some((start_reserved, reserved)) = self.get_last_reserved() { + start = start_reserved; + len = start + reserved; + } + if let Some((hole_start, gap)) = self.get_last_hole() + && hole_start > start + { + start = hole_start; + len = start + gap; + } + if let Some((region_start, region_index)) = self.get_last_region() + && region_start > start + { + len = region_start + + regions + .get_region_from_index(region_index) + .unwrap() + .read() + .reserved(); + } + len } pub fn get_last_region_index(&self) -> Option { self.get_last_region().map(|(_, index)| index) } - pub fn is_last_region(&self, index: usize) -> bool { - let last = self.get_last_region(); - let is_last = last.is_some_and(|(_, other_index)| index == other_index); - if is_last { - assert!(self.start_to_hole.range(last.unwrap().0..).next().is_none()); + pub fn get_last_region(&self) -> Option<(u64, usize)> { + self.start_to_index + .last_key_value() + .map(|(start, index)| (*start, *index)) + } + + fn get_last_hole(&self) -> Option<(u64, u64)> { + self.start_to_hole + .last_key_value() + .map(|(start, gap)| (*start, *gap)) + } + + fn get_last_reserved(&self) -> Option<(u64, u64)> { + self.start_to_reserved + .last_key_value() + .map(|(start, reserved)| (*start, *reserved)) + } + + pub fn is_last_anything(&self, index: usize) -> bool { + if let Some((last_start, last_index)) = self.get_last_region() + && last_index == index + && self + .get_last_hole() + .is_none_or(|(hole_start, _)| last_start > hole_start) + && self + .get_last_reserved() + .is_none_or(|(reserved_start, _)| last_start > reserved_start) + { + true + } else { + false } - is_last } pub fn insert_region(&mut self, start: u64, index: usize) { assert!(self.start_to_index.insert(start, index).is_none()) - // TODO: Other checks related to holes ? + // TODO: Other checks related to holes and reserved ? } pub fn move_region(&mut self, new_start: u64, index: usize, region: &Region) -> Result<()> { @@ -87,14 +134,15 @@ impl Layout { } pub fn remove_region(&mut self, index: usize, region: &Region) -> Result<()> { + // info!("Remove region {index}"); + let start = region.start(); let mut reserved = region.reserved(); - if self - .start_to_index - .remove(&start) - .is_none_or(|index_| index != index_) - { + let removed = self.start_to_index.remove(&start); + + if removed.is_none_or(|index_| index != index_) { + dbg!((index, removed)); return Err(Error::Str( "Something went wrong, indexes of removed region should be the same", )); @@ -105,19 +153,7 @@ impl Layout { .remove(&(start + reserved)) .unwrap_or_default(); - if self - .start_to_index - .keys() - .last() - .is_none_or(|®ion_start| { - self.start_to_hole - .keys() - .last() - .is_some_and(|&hole_start| hole_start > region_start) - }) - { - self.start_to_hole.pop_last(); - } else if let Some((&hole_start, gap)) = self.start_to_hole.range_mut(..start).next_back() + if let Some((&hole_start, gap)) = self.start_to_hole.range_mut(..start).next_back() && hole_start + *gap == start { *gap += reserved; @@ -142,7 +178,7 @@ impl Layout { .map(|(_, s)| *s) } - pub fn remove_or_compress_hole_to_right(&mut self, start: u64, compress_by: u64) { + pub fn remove_or_compress_hole(&mut self, start: u64, compress_by: u64) { if let Some(gap) = self.start_to_hole.remove(&start) && gap != compress_by { @@ -154,4 +190,10 @@ impl Layout { } } } + + pub fn reserve(&mut self, start: u64, reserved: u64) { + if self.start_to_reserved.insert(start, reserved).is_some() { + unreachable!(); + } + } } diff --git a/crates/brk_vecs/src/file/mod.rs b/crates/brk_vecs/src/file/mod.rs index 7570169f3..cce12cc85 100644 --- a/crates/brk_vecs/src/file/mod.rs +++ b/crates/brk_vecs/src/file/mod.rs @@ -99,7 +99,7 @@ impl File { let mut layout = self.layout.write(); let start = if let Some(start) = layout.find_smallest_adequate_hole(PAGE_SIZE) { - layout.remove_or_compress_hole_to_right(start, PAGE_SIZE); + layout.remove_or_compress_hole(start, PAGE_SIZE); start } else { let start = layout @@ -204,8 +204,6 @@ impl File { return Ok(()); } - // let layouat_lock = self.layout.read(); - assert!(new_len > reserved); let mut new_reserved = reserved; while new_len > new_reserved { @@ -217,22 +215,21 @@ impl File { let mut layout = self.layout.write(); // If is last continue writing - if layout.is_last_region(region_index) { + if layout.is_last_anything(region_index) { // println!( // "{region_index} Append to file at {}", // start + at.unwrap_or(len) // ); self.set_min_len(start + new_reserved)?; - - if at.is_none() { - self.write(start + len, data); - } let mut region = region_lock.write(); region.set_reserved(new_reserved); - if let Some(at) = at { - self.write(start + at, data); - } + drop(region); + drop(layout); + + self.write(start + len, data); + + let mut region = region_lock.write(); region.set_len(new_len); regions.write_to_mmap(®ion, region_index); @@ -247,19 +244,18 @@ impl File { { // println!("Expand {region_index} to hole"); - layout.remove_or_compress_hole_to_right(hole_start, added_reserve); - drop(layout); - - if at.is_none() { - self.write(start + len, data); - } + layout.remove_or_compress_hole(hole_start, added_reserve); let mut region = region_lock.write(); region.set_reserved(new_reserved); - if let Some(at) = at { - self.write(start + at, data); - } + drop(region); + drop(layout); + + self.write(start + len, data); + + let mut region = region_lock.write(); region.set_len(new_len); regions.write_to_mmap(®ion, region_index); + return Ok(()); } @@ -267,8 +263,8 @@ impl File { if let Some(hole_start) = layout.find_smallest_adequate_hole(new_reserved) { // println!("Move {region_index} to hole at {hole_start}"); - layout.remove_or_compress_hole_to_right(hole_start, new_reserved); - // drop(layout); + layout.remove_or_compress_hole(hole_start, new_reserved); + drop(layout); self.write( hole_start, @@ -276,39 +272,29 @@ impl File { ); self.write(hole_start + len, data); - // let mut layout = self.layout.write(); let mut region = region_lock.write(); + let mut layout = self.layout.write(); layout.move_region(hole_start, region_index, ®ion)?; + drop(layout); + region.set_start(hole_start); region.set_reserved(new_reserved); region.set_len(new_len); - - drop(layout); - regions.write_to_mmap(®ion, region_index); return Ok(()); } + let new_start = layout.len(®ions); // Write at the end - // let mut region_lock = region.write(); - let (last_region_start, last_region_index) = layout.get_last_region().unwrap(); - let new_start = last_region_start - + regions - .get_region_from_index(last_region_index) - .unwrap() - .read() - .reserved(); // println!( // "Move {region_index} to the end, from {start}..{} to {new_start}..{}", // start + reserved, // new_start + new_reserved // ); - self.set_min_len(new_start + new_reserved)?; - - let mut region = region_lock.write(); - layout.move_region(new_start, region_index, ®ion)?; + layout.reserve(new_start, new_reserved); + drop(layout); self.write( new_start, @@ -316,14 +302,14 @@ impl File { ); self.write(new_start + len, data); - // dbg!(new_start, region_index, ®ion_lock, new_reserved, new_len); + let mut region = region_lock.write(); + let mut layout = self.layout.write(); + layout.move_region(new_start, region_index, ®ion)?; + drop(layout); region.set_start(new_start); region.set_reserved(new_reserved); region.set_len(new_len); - - drop(layout); - regions.write_to_mmap(®ion, region_index); Ok(()) diff --git a/crates/brk_vecs/src/file/regions.rs b/crates/brk_vecs/src/file/regions.rs index c7773e86c..682089e0b 100644 --- a/crates/brk_vecs/src/file/regions.rs +++ b/crates/brk_vecs/src/file/regions.rs @@ -34,8 +34,7 @@ impl Regions { let id_to_index_path = path.join("id_to_index"); let id_to_index: HashMap = - deserialize_hashmap_binary(&fs::read(&id_to_index_path).unwrap_or_default()) - .unwrap_or_default(); + Self::deserialize(&fs::read(&id_to_index_path).unwrap_or_default()).unwrap_or_default(); let index_to_region_file = OpenOptions::new() .read(true) @@ -123,10 +122,7 @@ impl Regions { } fn flush_id_to_index(&mut self) -> Result<()> { - fs::write( - &self.id_to_index_path, - serialize_hashmap_binary(&self.id_to_index), - )?; + fs::write(&self.id_to_index_path, Self::serialize(&self.id_to_index))?; Ok(()) } @@ -231,52 +227,49 @@ impl Regions { pub fn flush(&self) -> Result<()> { self.index_to_region_mmap.flush().map_err(|e| e.into()) } -} -fn serialize_hashmap_binary(map: &HashMap) -> Vec { - let mut buffer = Vec::new(); + fn serialize(map: &HashMap) -> Vec { + let mut buffer = Vec::new(); - buffer.extend_from_slice(&map.len().to_ne_bytes()); + buffer.extend_from_slice(&map.len().to_ne_bytes()); - for (key, value) in map { - buffer.extend_from_slice(&key.len().to_ne_bytes()); - buffer.extend_from_slice(key.as_bytes()); - buffer.extend_from_slice(&value.to_ne_bytes()); + for (key, value) in map { + buffer.extend_from_slice(key.len().as_bytes()); + buffer.extend_from_slice(key.as_bytes()); + buffer.extend_from_slice(value.as_bytes()); + } + + buffer } - buffer -} - -fn deserialize_hashmap_binary(data: &[u8]) -> Result> { - let mut cursor = Cursor::new(data); - let mut buffer = [0u8; 8]; - - cursor - .read_exact(&mut buffer) - .map_err(|_| Error::Str("Failed to read entry count"))?; - let entry_count = usize::from_ne_bytes(buffer); - - let mut map = HashMap::with_capacity(entry_count); - - for _ in 0..entry_count { - cursor - .read_exact(&mut buffer) - .map_err(|_| Error::Str("Failed to read key length"))?; - let key_len = usize::from_ne_bytes(buffer); - - let mut key_bytes = vec![0u8; key_len]; - cursor - .read_exact(&mut key_bytes) - .map_err(|_| Error::Str("Failed to read key"))?; - let key = String::from_utf8(key_bytes).map_err(|_| Error::Str("Invalid UTF-8 in key"))?; + fn deserialize(data: &[u8]) -> Result> { + let mut cursor = Cursor::new(data); + let mut buffer = [0u8; 8]; cursor .read_exact(&mut buffer) - .map_err(|_| Error::Str("Failed to read value"))?; - let value = usize::from_ne_bytes(buffer); + .map_err(|_| Error::Str("Failed to read entry count"))?; + let entry_count = usize::read_from_bytes(&buffer)?; - map.insert(key, value); + let mut map = HashMap::with_capacity(entry_count); + + for _ in 0..entry_count { + cursor + .read_exact(&mut buffer) + .map_err(|_| Error::Str("Failed to read key length"))?; + let key_len = usize::read_from_bytes(&buffer)?; + + let mut key_bytes = vec![0u8; key_len]; + cursor.read_exact(&mut key_bytes)?; + let key = + String::from_utf8(key_bytes).map_err(|_| Error::Str("Invalid UTF-8 in key"))?; + + cursor.read_exact(&mut buffer)?; + let value = usize::read_from_bytes(&buffer)?; + + map.insert(key, value); + } + + Ok(map) } - - Ok(map) }