From 099699872e4fabd6e26826fb2280b734ebc37b50 Mon Sep 17 00:00:00 2001 From: nym21 Date: Thu, 2 Apr 2026 12:39:20 +0200 Subject: [PATCH] global: fixes --- crates/brk_client/src/lib.rs | 2 +- crates/brk_indexer/src/lib.rs | 31 ++++++++++++++++++++++++--- crates/brk_types/src/block.rs | 34 ++++++++++++++++++++++++++++++ website/scripts/options/partial.js | 4 ++-- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index 707290c23..5177878b3 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -8194,7 +8194,7 @@ pub struct BrkClient { impl BrkClient { /// Client version. - pub const VERSION: &'static str = "v0.2.5"; + pub const VERSION: &'static str = "v0.3.0-alpha.0"; /// Create a new client with the given base URL. pub fn new(base_url: impl Into) -> Self { diff --git a/crates/brk_indexer/src/lib.rs b/crates/brk_indexer/src/lib.rs index 4735898e7..7b377a8a5 100644 --- a/crates/brk_indexer/src/lib.rs +++ b/crates/brk_indexer/src/lib.rs @@ -2,13 +2,13 @@ use std::{ fs, - path::Path, + path::{Path, PathBuf}, thread::{self, sleep}, time::{Duration, Instant}, }; use brk_error::Result; -use brk_reader::Reader; +use brk_reader::{Reader, XORBytes}; use brk_rpc::Client; use brk_types::Height; use fjall::PersistMode; @@ -33,6 +33,7 @@ pub use stores::Stores; pub use vecs::*; pub struct Indexer { + path: PathBuf, pub vecs: Vecs, pub stores: Stores, } @@ -42,6 +43,7 @@ impl ReadOnlyClone for Indexer { fn read_only_clone(&self) -> Indexer { Indexer { + path: self.path.clone(), vecs: self.vecs.read_only_clone(), stores: self.stores.clone(), } @@ -75,7 +77,11 @@ impl Indexer { let stores = Stores::forced_import(&indexed_path, VERSION)?; info!("Imported stores in {:?}", i.elapsed()); - Ok(Self { vecs, stores }) + Ok(Self { + path: indexed_path.clone(), + vecs, + stores, + }) }; match try_import() { @@ -108,6 +114,23 @@ impl Indexer { self.index_(reader, client, exit, true) } + fn check_xor_bytes(&mut self, reader: &Reader) -> Result<()> { + let current = reader.xor_bytes(); + let cached = XORBytes::from(self.path.as_path()); + + if cached == current { + return Ok(()); + } + + info!("XOR bytes changed, full reset..."); + self.vecs.reset()?; + self.stores.reset()?; + + fs::write(self.path.join("xor.dat"), *current)?; + + Ok(()) + } + fn index_( &mut self, reader: &Reader, @@ -117,6 +140,8 @@ impl Indexer { ) -> Result { self.vecs.db.sync_bg_tasks()?; + self.check_xor_bytes(reader)?; + debug!("Starting indexing..."); let last_blockhash = self.vecs.blocks.blockhash.collect_last(); diff --git a/crates/brk_types/src/block.rs b/crates/brk_types/src/block.rs index 5b2369bd1..d64e8ac2a 100644 --- a/crates/brk_types/src/block.rs +++ b/crates/brk_types/src/block.rs @@ -185,3 +185,37 @@ impl ReadBlock { self.block } } + +#[cfg(test)] +mod tests { + use super::*; + use bitcoin::{Transaction, consensus::Decodable}; + + fn decode_hex(s: &str) -> Vec { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap()) + .collect() + } + + #[test] + fn hash_raw_tx_matches_compute_txid_for_segwit_tx() { + let hex = "0100000000010ad027250a29ef00b4fbab679d6d910054826a5ee679c70f69500fc2df02f87aea0400000000ffffffff93c9f683b46da97d2c631dccba17cb7c9dc5bd3c1afab3320bc4aa03369c201b0000000000ffffffff1e8170f5ad6680adcacb14ebce26d8584050b59b50fb83d5a1f958e99250b16e00000000fdfd000047304402200328e9ce339c90f5211a9c7c3315b0db27cbf554b383397bf0d50cfd4c5a150d022020f439553ed1712c63429073aa5811198e6d0db0606229540836380054d6ddcb014830450221009ed16332377d8bec8ea2cf59f7f4f6eb72eb0d9ff7fe12693cd400d84bde6eca0220563dd7fc2cd248d695ff38380efc7e27d99eb599815008b9baae7c4600e84284014c69522102a30752dcbbde99be02549ef88bc4d48122f0622c14aebe2dc20fe3f97101270a210256edf7f7bec24b7e4d11e49494a2147dc83c7dfd5bb3cc452181b2215c160bdd21033f5794f9a4640d35f42b132b552487d2ba0c5c3888380b66a3b16d2f366ce51b53aeffffffff09ad2196dd3dc106ac773f31e8918aa0a533daa1d3ad4db0cdb4df08750b061b77010000fdfd0000483045022100de89da280706a5cecb6472647df34c81f24c34f37f32c3fca07d64ce495e94f0022044048eeb71740e3b90540303688341584bc1b5f2459e104f1c52fdf2b047b4590147304402202a3ff42d0650d311e180f80019d7cc141e27c4706e9a79a1b2ff2f83bdc840eb02207cc28198d76bd2b5e7043b59025ef269301b337a0c5468ce9f7c332ce302d608014c69522102831ed7a372b37b803bd28cf987fde03a76ac873e0c801ba98309a08d043f9987210375adeb1ac333d7d0776ed8663e567bb129f76ad9d590435354307ab396350d082103407713929ce2e1b1f6f66d314a96db5b0aead3b47a2136a6e9feb4aed237972253aeffffffffaacd884cd7719ad1f1f49c6fed68449e50dfc11c7264559171a0f9220d998fab0100000000ffffffffa994c3b8c0acffbc5cd948fb01239ea3e89079be768822e56e98a0d868f9e46300000000fdfd0000483045022100ac6b08eab37b9e603951109f46ba54c69c3e399e5943015fdea76af263028c87022045fb7894781d8ce7f015bba655a9aa32fe54e16ace9911fad73ca39541f3126401473044022067654eaacbdb49b9c1ad55ca3319eb6a15d49019ffddc0329959e89160bfbba2022066943b9a869145940da4db58db36fe8c1bb8510827bd09327edbb938120c9bd5014c6952210393d7f2b624b51d8807be5dd1111f69b42d6422a2d073621684a011ce9743c7792102d5627dd55b9b5f99de1d52554e512022a424c360fe1c069a6c13c6cc5376effc2103747cb24063c911b5b31e94b058d04e17d86422c52c07d6c47db6b74d12c060ea53aeffffffffbb395a98a515b625ec35b41dcfc0cb9a225816abd676cf4fd950120e70e387120000000000ffffffff62872b622e250f6a067b0ef1e63ee6fa958b51f90c78dde02f5e8da90f8066d500000000fdfd0000483045022100cd1b0dd9404279b862d6a155ffbe894cd5e2285ec04f6eab61a17d4244049c9a02203ca5b49c55ef08ee6f25cfc329ae2acb7b60be46a72e3bb00485d2feba425cc101473044022018d643afccb3418c33b84eefe86de6baec695c5a5481c31e41fa22aedaed067402204529a1382d8d3e1ad7ace4709466f5df72c6e069166b28284c64c4e5278839d2014c695221037a06cea95b189aafe1e15b1eb931db5cf559beaf394cbc32ae5856b3e9814c132102e22967dd22d7740cd2c9d7fbd39f436ff611dc66d8043e077fec4732da704e052102035b82c21f2819595d72a665f4f4b5cb755a4756b4aa07812e4b825473e3748753aeffffffff127d9aa6f11a32f29d89be6e2837564162d911e3ab955be66c50c7fff8ad9bee00000000fc0047304402203988842a765e875f3931b764ec27b0dc9c5681188145a1a0dcf98fca44b7a93b02200d315a3f3648bec8a44c4db2edf2d9875197cc380ae9f1ccbf04e211af178c950147304402202e26adf91def55e8e54d32dbd339a7ef7a22e263518f3910073960fbdf2fee880220372c5dc1c6db8a36aa68dc2d9c0d300bacc882a61503bff4af7b4ebca92bd8c4014c69522103dbf9d0d0ecf6c1999c11c455677e8ebae5de2ffbab90954632aab0a9a257f21f21037480f7a31eb7a60db9c7e9f0a99b14bffd73014a3902a1d501820c3cdd51fc532103aa1e66aebe111353ff9febe0aa3c03f3acb7d339fa1c0811271ae951dd8bdc6353aeffffffff7487c6c1463948fe863431a1da6a4ff91baaa44606bc575fe980b1e86c9e9be00800000000ffffffff11705d010000000000225120ce4ab52fc4e6eea74c7db277bac6d9b9325fde9253039513b1de9782f452587ac0273500000000001976a9144210f6f3929a7fc2b25e96636c740cd7935b883d88ac4897e11100000000160014ea688c32414aebe4556dcd42301112dc06fa7290f661ad0000000000160014224b6524062a25b67cb5c1df918443b7c2e129689d211d0000000000225120cb8f606f894c983d1a644e60787e1ebef78ebc4ba760a3e230a7cd0cdfbec450144704000000000017a91462122c29b2ca069322c2daf6b19711a3e0ea595687bb5444020000000022512087f33c6febffa9ff60af09216a5897c5ab8638caaa3322779f02842862e3ac995ac90000000000001600148e5ab09208d65672994de460f70fc932feb269795809030000000000160014a310664053baef6ebda995ae758322f7c9ab2db56cdc0f000000000022512089ab10c68d292f5a00acca284b4f8712f0e6482dad4a3d0ad67c60a52086ef96012807000000000016001455621c3abb99d39577c19184ee816d10b578d6d5a08e030000000000160014dcf2b597675b3b375fb74735dfc44cadba18f19100b60200000000001600143ad99e76508462f0c119ab9c174937c56fede6ab2eaa430200000000220020ef90c2de160bb4939dfbcb13b530aef51b83f8ccf045709cc7ff8ed534dbb3db17472700000000001976a914d6065a5aad907d0f3f22e2962475355e6406dd7288ac1f610100000000001600148d0fd4724281d72f84774d99f4878cd0681e9ae631d0960300000000220020e5c7c00d174631d2d1e365d6347b016fb87b6a0c08902d8e443989cb771fa7ec04004730440220011789ebda70dec9c8bffec5a362ddf29cee2be3f5f9180b514af376ce0d077302205a38b773555e4795dc156286a4dab915b9a5eb60dbd3e2ba192ab35512290c7b0147304402206753092d5902dc26a93deb06c19a4b434563f8d94d718ced82ff3806cc38b59902205d1b604e9cb15728c7980b68ff29fe87ec380dc973756d9aa34e4cffb05a38360169522102ee39e562700f3793caa280d583e7be8dcae6b93fba64ee36204ea1b2ff39f24f2102249d182ac68b5379e9c31bc4773a6d150f437ae8077bd54fa9d7e62f4afbeb762103b1a1f84d381a9807a6ab1d7be0d7a5389cdaf226bdb68c23266c700281937c6f53ae0400483045022100a48324f241bc59374b54e3d1dacef1b1e713366c3af2bfeb438ab3e5d7822247022076be22d14fc628ed9123a38dbdc603073b79a531a2a0da3fefa6b4c29f3dc34d01473044022038546446cbbae00a41b14b2849556add6cf8b858bc445565fec4901922a1512d0220055c3f8dd44a00ccd3d3dee938f4d33a63411de71aea196aed7b223279f3d5eb016952210362c6286246c0dc9ff357fd98c298ce2da405e7d27536e4bc260586b678b3d8592103eec4a13ef4a65c5eae1602e2338e22a32997a25b6534698c606cb0560cba15ad210299f5b9d4f378005d67b9d77f762abb6070d02b7983895499efefe6f2341c579253ae0000040047304402202dcc5baba068b9ae48652af80d1c2ca2b445347db01cbf1f794d208c8087868c02200bb0cbc83f1d3075ed931c46688636152aaf87ad328e561a4220f3c690f9657f01473044022020bf84afc514f50222e5e7df62f158c56fad064c0c993a1ca021f22b48f41b6a0220546b24c9133c3b16cdb9289314b9b0ef012f33b276a8ef4f2b80206cdd1f2bb601695221023f0345f574652e6952fa9d288b3ba38cc15c09277decaa0e06ef1771f515f38721024274e29f6bb7569841c384b52828209e77bb0db0569c969e7aa386ce2768dc37210398d63ca1f2eed732371d7a36e8f41da050c14031a9adee29c8c2f246dbee06d653ae000400483045022100c1b84e2d9f2c83ea19668881f453caaf40856e2fa6b86361ced62644ac387522022022b8787394809f5406f9188478537128ad9a5e02677afca22a80f136b941de8301483045022100e6caad435ebffe06576446c95e5900f79eda75dcccf6a177442d2c82f947836202205fb7473dbc444d7dd436497da60533397d2468d0a30edb6b3ed514b466995dba016952210205ce9f2ad24fe1221ae503f67bb0ecc759e0c5945c8df2158d8ba5bf262c570c21023a05a46bd80a1a5c6c727704d9e9ddba74590041ae52524090b5ebc779d84a462102543352c636506f63617f7c6d6ec44cc808e36ebb8af4bd04dc61961fe7531cbc53ae00000400473044022025d75591d74390dd3fa267b9dd2bb2f8d1adfb4bab787a3f6ad33d0958a15f6c022039352e6caeae77fc8a0c5ef5e27fe414488c145420f01ab62cf03373cd7fdd3701483045022100eaac10703e5aab0b6db6c127f723c2be88f5c0790e1377727ab7250c6c1b29ec022012b6386a067b9e244698d1972f4fbe8d4d04859b69a6f8311406cdf325502ee901695221026064e5b88c4fff7dba7dc0300db8dbfc1faff14f9ddbaacbcaa4f70124de0e93210331870350912385ca9a9d537e9cf9d80c6c9558e31d654f82f3164fdc5955e9642103c7b133a0f463a501d8c58c8eb8c7b6e9e4ddfb7d4a7bf6365a4732201569bc8353ae00000000"; + let raw = decode_hex(hex); + let tx = Transaction::consensus_decode(&mut &raw[..]).unwrap(); + + let expected_txid = tx.compute_txid(); + assert_eq!( + expected_txid.to_string(), + "3595e70d423e7a28c6a865322d30e49e98d377cd93e0b53d133ca7397d9d752e" + ); + + let base_size = tx.base_size() as u32; + let total_size = raw.len() as u32; + assert_ne!(base_size, total_size, "should be segwit"); + assert_eq!(raw[4], 0x00, "segwit marker"); + + let raw_txid = Block::hash_raw_tx(&raw, base_size); + assert_eq!(raw_txid, expected_txid, "hash_raw_tx must match compute_txid"); + } +} diff --git a/website/scripts/options/partial.js b/website/scripts/options/partial.js index 1d36e7ab2..f1aa9ace2 100644 --- a/website/scripts/options/partial.js +++ b/website/scripts/options/partial.js @@ -59,11 +59,11 @@ export function createPartialOptions() { return [ ...(location.hostname === "localhost" || location.hostname === "127.0.0.1" ? [ - { + /** @type {any} */ ({ name: "Explorer", kind: "explorer", title: "Explorer", - }, + }), ] : []), {