computer: fix stateful

This commit is contained in:
nym21
2025-07-17 11:35:40 +02:00
parent a0cfc1be2b
commit c07e66c086
16 changed files with 340 additions and 105 deletions

View File

@@ -1,4 +1,4 @@
use std::{collections::BTreeSet, mem};
use std::collections::BTreeSet;
use brk_core::TypeIndex;
use derive_deref::{Deref, DerefMut};
@@ -8,29 +8,6 @@ use super::ByAddressType;
#[derive(Debug, Deref, DerefMut)]
pub struct AddressTypeToTypeIndexSet(ByAddressType<BTreeSet<TypeIndex>>);
impl AddressTypeToTypeIndexSet {
pub fn merge(mut self, mut other: Self) -> Self {
Self::merge_(&mut self.p2pk65, &mut other.p2pk65);
Self::merge_(&mut self.p2pk33, &mut other.p2pk33);
Self::merge_(&mut self.p2pkh, &mut other.p2pkh);
Self::merge_(&mut self.p2sh, &mut other.p2sh);
Self::merge_(&mut self.p2wpkh, &mut other.p2wpkh);
Self::merge_(&mut self.p2wsh, &mut other.p2wsh);
Self::merge_(&mut self.p2tr, &mut other.p2tr);
Self::merge_(&mut self.p2a, &mut other.p2a);
self
}
fn merge_(own: &mut BTreeSet<TypeIndex>, other: &mut BTreeSet<TypeIndex>) {
if own.len() >= other.len() {
own.append(other);
} else {
other.append(own);
mem::swap(own, other);
}
}
}
impl Default for AddressTypeToTypeIndexSet {
fn default() -> Self {
Self(ByAddressType {

View File

@@ -29,10 +29,6 @@ impl<T> AddressTypeToTypeIndexTree<T> {
mem::swap(own, other);
}
}
pub fn unwrap(self) -> ByAddressType<BTreeMap<TypeIndex, T>> {
self.0
}
}
impl<T> Default for AddressTypeToTypeIndexTree<T> {

View File

@@ -55,7 +55,7 @@ use range_map::*;
use r#trait::*;
pub use withaddressdatasource::WithAddressDataSource;
const VERSION: Version = Version::new(18);
const VERSION: Version = Version::new(19);
#[derive(Clone)]
pub struct Vecs {
@@ -1188,20 +1188,10 @@ impl Vecs {
if height != Height::ZERO && height.unwrap_to_usize() % 10_000 == 0 {
info!("Flushing...");
exit.block();
self.flush_states(height, &chain_state, exit)?;
// Maybe keep some from the end for both
let addresstype_to_typeindex_to_loadedaddressdata_to_consume =
mem::take(&mut addresstype_to_typeindex_to_loadedaddressdata);
let addresstype_to_typeindex_to_emptyaddressdata_to_consume =
mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata);
// stores.commit(
// height,
// addresstype_to_typeindex_to_loadedaddressdata_to_consume,
// addresstype_to_typeindex_to_emptyaddressdata_to_consume,
// )?;
self.flush_states(height, &chain_state, mem::take(&mut addresstype_to_typeindex_to_loadedaddressdata), mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata), exit)?;
self.reset_mmaps_options(
&mut addresstypeindex_to_anyaddressindex_mmap_opt,
@@ -1218,12 +1208,13 @@ impl Vecs {
info!("Flushing...");
self.flush_states(height, &chain_state, exit)?;
// stores.commit(
// height,
// mem::take(&mut addresstype_to_typeindex_to_loadedaddressdata),
// mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata),
// )?;
self.flush_states(
height,
&chain_state,
mem::take(&mut addresstype_to_typeindex_to_loadedaddressdata),
mem::take(&mut addresstype_to_typeindex_to_emptyaddressdata),
exit,
)?;
} else {
exit.block();
}
@@ -1488,33 +1479,39 @@ impl Vecs {
.into_owned();
Some(match anyaddressindex.to_enum() {
AnyAddressDataIndexEnum::Loaded(index) => {
AnyAddressDataIndexEnum::Loaded(loadedaddressindex) => {
let mmap = anyaddressindex_to_anyaddressdata_mmap_opt
.loaded
.as_ref()
.unwrap();
let loadedaddressdata = loadedaddressindex_to_loadedaddressdata
.get_or_read(index, mmap)
.get_or_read(loadedaddressindex, mmap)
.unwrap()
.unwrap()
.into_owned();
WithAddressDataSource::FromLoadedAddressDataVec(loadedaddressdata)
WithAddressDataSource::FromLoadedAddressDataVec((
loadedaddressindex,
loadedaddressdata,
))
}
AnyAddressDataIndexEnum::Empty(index) => {
AnyAddressDataIndexEnum::Empty(emtpyaddressindex) => {
let mmap = anyaddressindex_to_anyaddressdata_mmap_opt
.empty
.as_ref()
.unwrap();
let emptyaddressdata = emptyaddressindex_to_emptyaddressdata
.get_or_read(index, mmap)
.get_or_read(emtpyaddressindex, mmap)
.unwrap()
.unwrap()
.into_owned();
WithAddressDataSource::FromEmptyAddressDataVec(emptyaddressdata.into())
WithAddressDataSource::FromEmptyAddressDataVec((
emtpyaddressindex,
emptyaddressdata.into(),
))
}
})
}
@@ -1580,6 +1577,12 @@ impl Vecs {
&mut self,
height: Height,
chain_state: &[BlockState],
mut addresstype_to_typeindex_to_loadedaddressdata: AddressTypeToTypeIndexTree<
WithAddressDataSource<LoadedAddressData>,
>,
mut addresstype_to_typeindex_to_emptyaddressdata: AddressTypeToTypeIndexTree<
WithAddressDataSource<EmptyAddressData>,
>,
exit: &Exit,
) -> Result<()> {
self.utxo_cohorts
@@ -1601,6 +1604,149 @@ impl Vecs {
.into_iter()
.try_for_each(|v| v.safe_flush(exit))?;
let mut addresstype_to_typeindex_to_new_or_updated_anyaddressindex =
AddressTypeToTypeIndexTree::default();
addresstype_to_typeindex_to_emptyaddressdata
.into_typed_vec()
.into_iter()
.try_for_each(|(_type, tree)| -> Result<()> {
tree.into_iter().try_for_each(
|(typeindex, emptyaddressdata_with_source)| -> Result<()> {
match emptyaddressdata_with_source {
WithAddressDataSource::New(emptyaddressdata) => {
let emptyaddressindex = self
.emptyaddressindex_to_emptyaddressdata
.fill_first_hole_or_push(emptyaddressdata)?;
let anyaddressindex = AnyAddressIndex::from(emptyaddressindex);
addresstype_to_typeindex_to_new_or_updated_anyaddressindex
.get_mut(_type)
.unwrap()
.insert(typeindex, anyaddressindex);
Ok(())
}
WithAddressDataSource::FromEmptyAddressDataVec((
emptyaddressindex,
emptyaddressdata,
)) => self
.emptyaddressindex_to_emptyaddressdata
.update(emptyaddressindex, emptyaddressdata),
WithAddressDataSource::FromLoadedAddressDataVec((
loadedaddressindex,
emptyaddressdata,
)) => {
self.loadedaddressindex_to_loadedaddressdata
.delete(loadedaddressindex);
let emptyaddressindex = self
.emptyaddressindex_to_emptyaddressdata
.fill_first_hole_or_push(emptyaddressdata)?;
let anyaddressindex = emptyaddressindex.into();
addresstype_to_typeindex_to_new_or_updated_anyaddressindex
.get_mut(_type)
.unwrap()
.insert(typeindex, anyaddressindex);
Ok(())
}
}
},
)
})?;
addresstype_to_typeindex_to_loadedaddressdata
.into_typed_vec()
.into_iter()
.try_for_each(|(_type, tree)| -> Result<()> {
tree.into_iter().try_for_each(
|(typeindex, loadedaddressdata_with_source)| -> Result<()> {
match loadedaddressdata_with_source {
WithAddressDataSource::New(loadedaddressdata) => {
let loadedaddressindex = self
.loadedaddressindex_to_loadedaddressdata
.fill_first_hole_or_push(loadedaddressdata)?;
let anyaddressindex = AnyAddressIndex::from(loadedaddressindex);
addresstype_to_typeindex_to_new_or_updated_anyaddressindex
.get_mut(_type)
.unwrap()
.insert(typeindex, anyaddressindex);
Ok(())
}
WithAddressDataSource::FromLoadedAddressDataVec((
loadedaddressindex,
loadedaddressdata,
)) => self
.loadedaddressindex_to_loadedaddressdata
.update(loadedaddressindex, loadedaddressdata),
WithAddressDataSource::FromEmptyAddressDataVec((
emptyaddressindex,
loadedaddressdata,
)) => {
self.emptyaddressindex_to_emptyaddressdata
.delete(emptyaddressindex);
let loadedaddressindex = self
.loadedaddressindex_to_loadedaddressdata
.fill_first_hole_or_push(loadedaddressdata)?;
let anyaddressindex = loadedaddressindex.into();
addresstype_to_typeindex_to_new_or_updated_anyaddressindex
.get_mut(_type)
.unwrap()
.insert(typeindex, anyaddressindex);
Ok(())
}
}
},
)
})?;
addresstype_to_typeindex_to_new_or_updated_anyaddressindex
.into_typed_vec()
.into_iter()
.try_for_each(|(_type, tree)| -> Result<()> {
tree.into_iter()
.try_for_each(|(typeindex, anyaddressindex)| -> Result<()> {
match _type {
OutputType::P2PK33 => self
.p2pk33addressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2PK65 => self
.p2pk65addressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2PKH => self
.p2pkhaddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2SH => self
.p2shaddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2TR => self
.p2traddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2WPKH => self
.p2wpkhaddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2WSH => self
.p2wshaddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
OutputType::P2A => self
.p2aaddressindex_to_anyaddressindex
.update_or_push(typeindex.into(), anyaddressindex),
_ => unreachable!(),
}
})
})?;
self.p2pk33addressindex_to_anyaddressindex.flush(height)?;
self.p2pk65addressindex_to_anyaddressindex.flush(height)?;
self.p2pkhaddressindex_to_anyaddressindex.flush(height)?;

View File

@@ -1,10 +1,10 @@
use brk_core::{EmptyAddressData, LoadedAddressData};
use brk_core::{EmptyAddressData, EmptyAddressIndex, LoadedAddressData, LoadedAddressIndex};
#[derive(Debug)]
pub enum WithAddressDataSource<T> {
New(T),
FromLoadedAddressDataVec(T),
FromEmptyAddressDataVec(T),
FromLoadedAddressDataVec((LoadedAddressIndex, T)),
FromEmptyAddressDataVec((EmptyAddressIndex, T)),
}
impl<T> WithAddressDataSource<T> {
@@ -12,27 +12,15 @@ impl<T> WithAddressDataSource<T> {
matches!(self, Self::New(_))
}
pub fn is_from_addressdata(&self) -> bool {
matches!(self, Self::FromLoadedAddressDataVec(_))
}
pub fn is_from_emptyaddressdata(&self) -> bool {
matches!(self, Self::FromEmptyAddressDataVec(_))
}
pub fn deref(&self) -> &T {
match self {
Self::New(v) => v,
Self::FromLoadedAddressDataVec(v) => v,
Self::FromEmptyAddressDataVec(v) => v,
}
}
pub fn deref_mut(&mut self) -> &mut T {
match self {
Self::New(v) => v,
Self::FromLoadedAddressDataVec(v) => v,
Self::FromEmptyAddressDataVec(v) => v,
Self::FromLoadedAddressDataVec((_, v)) => v,
Self::FromEmptyAddressDataVec((_, v)) => v,
}
}
}
@@ -41,11 +29,11 @@ impl From<WithAddressDataSource<EmptyAddressData>> for WithAddressDataSource<Loa
fn from(value: WithAddressDataSource<EmptyAddressData>) -> Self {
match value {
WithAddressDataSource::New(v) => Self::New(v.into()),
WithAddressDataSource::FromLoadedAddressDataVec(v) => {
Self::FromLoadedAddressDataVec(v.into())
WithAddressDataSource::FromLoadedAddressDataVec((i, v)) => {
Self::FromLoadedAddressDataVec((i, v.into()))
}
WithAddressDataSource::FromEmptyAddressDataVec(v) => {
Self::FromEmptyAddressDataVec(v.into())
WithAddressDataSource::FromEmptyAddressDataVec((i, v)) => {
Self::FromEmptyAddressDataVec((i, v.into()))
}
}
}
@@ -55,11 +43,11 @@ impl From<WithAddressDataSource<LoadedAddressData>> for WithAddressDataSource<Em
fn from(value: WithAddressDataSource<LoadedAddressData>) -> Self {
match value {
WithAddressDataSource::New(v) => Self::New(v.into()),
WithAddressDataSource::FromLoadedAddressDataVec(v) => {
Self::FromLoadedAddressDataVec(v.into())
WithAddressDataSource::FromLoadedAddressDataVec((i, v)) => {
Self::FromLoadedAddressDataVec((i, v.into()))
}
WithAddressDataSource::FromEmptyAddressDataVec(v) => {
Self::FromEmptyAddressDataVec(v.into())
WithAddressDataSource::FromEmptyAddressDataVec((i, v)) => {
Self::FromEmptyAddressDataVec((i, v.into()))
}
}
}