mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-13 20:08:36 -07:00
global: utxos part 7
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use std::ops::{Add, AddAssign, SubAssign};
|
use std::ops::{Add, AddAssign, SubAssign};
|
||||||
|
|
||||||
use brk_core::{Dollars, Sats, Timestamp};
|
use brk_core::{Dollars, Timestamp};
|
||||||
|
|
||||||
use super::{OutputsByType, SupplyState};
|
use super::SupplyState;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BlockState {
|
pub struct BlockState {
|
||||||
@@ -30,33 +30,3 @@ impl SubAssign<&BlockState> for BlockState {
|
|||||||
self.supply -= &rhs.supply;
|
self.supply -= &rhs.supply;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReceivedBlockStateData<'a> {
|
|
||||||
pub received: &'a OutputsByType<(SupplyState, Vec<Sats>)>,
|
|
||||||
pub timestamp: Timestamp,
|
|
||||||
pub price: Option<Dollars>,
|
|
||||||
}
|
|
||||||
impl<'a> From<ReceivedBlockStateData<'a>> for BlockState {
|
|
||||||
fn from(
|
|
||||||
ReceivedBlockStateData {
|
|
||||||
received,
|
|
||||||
timestamp,
|
|
||||||
price,
|
|
||||||
}: ReceivedBlockStateData<'a>,
|
|
||||||
) -> Self {
|
|
||||||
let mut block_state = BlockState {
|
|
||||||
supply: SupplyState::default(),
|
|
||||||
price,
|
|
||||||
timestamp,
|
|
||||||
};
|
|
||||||
received
|
|
||||||
.spendable
|
|
||||||
.as_vec()
|
|
||||||
.into_iter()
|
|
||||||
.for_each(|spendable_block_state| {
|
|
||||||
block_state.supply += &spendable_block_state.0;
|
|
||||||
});
|
|
||||||
block_state.supply.utxos += received.unspendable.empty.0.utxos;
|
|
||||||
block_state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
use brk_core::{Bitcoin, CheckedSub, Dollars};
|
use brk_core::Dollars;
|
||||||
|
|
||||||
use super::SupplyState;
|
use super::{RealizedState, SupplyState};
|
||||||
|
|
||||||
// Vecs ? probably
|
// Vecs ? probably
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct CohortState {
|
pub struct CohortState {
|
||||||
pub supply: SupplyState,
|
pub supply: SupplyState,
|
||||||
pub realized_cap: Option<Dollars>,
|
pub realized: Option<RealizedState>,
|
||||||
// pub price_to_amount: PriceToValue<Amount>, save it not rounded in fjall
|
// pub price_to_amount: PriceToValue<Amount>, save it not rounded in fjall
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CohortState {
|
impl CohortState {
|
||||||
pub fn increment(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
pub fn increment(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
||||||
self.supply += supply_state;
|
self.supply += supply_state;
|
||||||
if let Some(realized_cap) = self.realized_cap.as_mut() {
|
if let Some(realized) = self.realized.as_mut() {
|
||||||
*realized_cap += price.unwrap() * Bitcoin::from(supply_state.value);
|
realized.increment(supply_state, price.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrement(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
pub fn decrement(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
||||||
if let Some(realized_cap) = self.realized_cap.as_mut() {
|
|
||||||
*realized_cap = realized_cap
|
|
||||||
.checked_sub(price.unwrap() * Bitcoin::from(supply_state.value))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
self.supply -= supply_state;
|
self.supply -= supply_state;
|
||||||
|
if let Some(realized) = self.realized.as_mut() {
|
||||||
|
realized.decrement(supply_state, price.unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
mod block;
|
mod block;
|
||||||
mod cohort;
|
mod cohort;
|
||||||
mod outputs;
|
mod outputs;
|
||||||
// mod realized;
|
mod realized;
|
||||||
// mod hot;
|
// mod hot;
|
||||||
mod supply;
|
mod supply;
|
||||||
|
mod transacted;
|
||||||
|
|
||||||
pub use block::*;
|
pub use block::*;
|
||||||
pub use cohort::*;
|
pub use cohort::*;
|
||||||
pub use outputs::*;
|
pub use outputs::*;
|
||||||
// pub use realized::*;
|
pub use realized::*;
|
||||||
// pub use hot::*;
|
// pub use hot::*;
|
||||||
pub use supply::*;
|
pub use supply::*;
|
||||||
|
pub use transacted::*;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use brk_core::Sats;
|
|
||||||
|
|
||||||
use super::OutputFilter;
|
use super::OutputFilter;
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct OutputsBySize<T> {
|
pub struct OutputsBySize<T> {
|
||||||
|
pub _0sat: T,
|
||||||
pub from_1sat_to_10sats: T,
|
pub from_1sat_to_10sats: T,
|
||||||
pub from_10sats_to_100sats: T,
|
pub from_10sats_to_100sats: T,
|
||||||
pub from_100sats_to_1_000sats: T,
|
pub from_100sats_to_1_000sats: T,
|
||||||
@@ -24,60 +23,79 @@ impl<T> From<OutputsBySize<T>> for OutputsBySize<(OutputFilter, T)> {
|
|||||||
fn from(value: OutputsBySize<T>) -> Self {
|
fn from(value: OutputsBySize<T>) -> Self {
|
||||||
#[allow(clippy::inconsistent_digit_grouping)]
|
#[allow(clippy::inconsistent_digit_grouping)]
|
||||||
Self {
|
Self {
|
||||||
|
_0sat: (
|
||||||
|
// OutputFilter::Zero,
|
||||||
|
OutputFilter::Size,
|
||||||
|
value._0sat,
|
||||||
|
),
|
||||||
from_1sat_to_10sats: (
|
from_1sat_to_10sats: (
|
||||||
OutputFilter::Size(Sats::new(1)..Sats::new(10)),
|
// OutputFilter::Size(Sats::new(1)..Sats::new(10)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_1sat_to_10sats,
|
value.from_1sat_to_10sats,
|
||||||
),
|
),
|
||||||
from_10sats_to_100sats: (
|
from_10sats_to_100sats: (
|
||||||
OutputFilter::Size(Sats::new(10)..Sats::new(100)),
|
// OutputFilter::Size(Sats::new(10)..Sats::new(100)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_10sats_to_100sats,
|
value.from_10sats_to_100sats,
|
||||||
),
|
),
|
||||||
from_100sats_to_1_000sats: (
|
from_100sats_to_1_000sats: (
|
||||||
OutputFilter::Size(Sats::new(100)..Sats::new(1_000)),
|
// OutputFilter::Size(Sats::new(100)..Sats::new(1_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_100sats_to_1_000sats,
|
value.from_100sats_to_1_000sats,
|
||||||
),
|
),
|
||||||
from_1_000sats_to_10_000sats: (
|
from_1_000sats_to_10_000sats: (
|
||||||
OutputFilter::Size(Sats::new(1_000)..Sats::new(10_000)),
|
// OutputFilter::Size(Sats::new(1_000)..Sats::new(10_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_1_000sats_to_10_000sats,
|
value.from_1_000sats_to_10_000sats,
|
||||||
),
|
),
|
||||||
from_10_000sats_to_100_000sats: (
|
from_10_000sats_to_100_000sats: (
|
||||||
OutputFilter::Size(Sats::new(10_000)..Sats::new(100_000)),
|
// OutputFilter::Size(Sats::new(10_000)..Sats::new(100_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_10_000sats_to_100_000sats,
|
value.from_10_000sats_to_100_000sats,
|
||||||
),
|
),
|
||||||
from_100_000sats_to_1_000_000sats: (
|
from_100_000sats_to_1_000_000sats: (
|
||||||
OutputFilter::Size(Sats::new(100_000)..Sats::new(1_000_000)),
|
// OutputFilter::Size(Sats::new(100_000)..Sats::new(1_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_100_000sats_to_1_000_000sats,
|
value.from_100_000sats_to_1_000_000sats,
|
||||||
),
|
),
|
||||||
from_1_000_000sats_to_10_000_000sats: (
|
from_1_000_000sats_to_10_000_000sats: (
|
||||||
OutputFilter::Size(Sats::new(1_000_000)..Sats::new(10_000_000)),
|
// OutputFilter::Size(Sats::new(1_000_000)..Sats::new(10_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_1_000_000sats_to_10_000_000sats,
|
value.from_1_000_000sats_to_10_000_000sats,
|
||||||
),
|
),
|
||||||
from_10_000_000sats_to_1btc: (
|
from_10_000_000sats_to_1btc: (
|
||||||
OutputFilter::Size(Sats::new(10_000_000)..Sats::new(1_00_000_000)),
|
// OutputFilter::Size(Sats::new(10_000_000)..Sats::new(1_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_10_000_000sats_to_1btc,
|
value.from_10_000_000sats_to_1btc,
|
||||||
),
|
),
|
||||||
from_1btc_to_10btc: (
|
from_1btc_to_10btc: (
|
||||||
OutputFilter::Size(Sats::new(1_00_000_000)..Sats::new(10_00_000_000)),
|
// OutputFilter::Size(Sats::new(1_00_000_000)..Sats::new(10_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_1btc_to_10btc,
|
value.from_1btc_to_10btc,
|
||||||
),
|
),
|
||||||
from_10btc_to_100btc: (
|
from_10btc_to_100btc: (
|
||||||
OutputFilter::Size(Sats::new(10_00_000_000)..Sats::new(100_00_000_000)),
|
// OutputFilter::Size(Sats::new(10_00_000_000)..Sats::new(100_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_10btc_to_100btc,
|
value.from_10btc_to_100btc,
|
||||||
),
|
),
|
||||||
from_100btc_to_1_000btc: (
|
from_100btc_to_1_000btc: (
|
||||||
OutputFilter::Size(Sats::new(100_00_000_000)..Sats::new(1_000_00_000_000)),
|
// OutputFilter::Size(Sats::new(100_00_000_000)..Sats::new(1_000_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_100btc_to_1_000btc,
|
value.from_100btc_to_1_000btc,
|
||||||
),
|
),
|
||||||
from_1_000btc_to_10_000btc: (
|
from_1_000btc_to_10_000btc: (
|
||||||
OutputFilter::Size(Sats::new(1_000_00_000_000)..Sats::new(10_000_00_000_000)),
|
// OutputFilter::Size(Sats::new(1_000_00_000_000)..Sats::new(10_000_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_1_000btc_to_10_000btc,
|
value.from_1_000btc_to_10_000btc,
|
||||||
),
|
),
|
||||||
from_10_000btc_to_100_000btc: (
|
from_10_000btc_to_100_000btc: (
|
||||||
OutputFilter::Size(Sats::new(10_000_00_000_000)..Sats::new(100_000_00_000_000)),
|
// OutputFilter::Size(Sats::new(10_000_00_000_000)..Sats::new(100_000_00_000_000)),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_10_000btc_to_100_000btc,
|
value.from_10_000btc_to_100_000btc,
|
||||||
),
|
),
|
||||||
from_100_000btc: (
|
from_100_000btc: (
|
||||||
OutputFilter::Size(Sats::new(100_000_00_000_000)..Sats::MAX),
|
// OutputFilter::Size(Sats::new(100_000_00_000_000)..Sats::MAX),
|
||||||
|
OutputFilter::Size,
|
||||||
value.from_100_000btc,
|
value.from_100_000btc,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -85,8 +103,44 @@ impl<T> From<OutputsBySize<T>> for OutputsBySize<(OutputFilter, T)> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsBySize<T> {
|
impl<T> OutputsBySize<T> {
|
||||||
pub fn as_mut_vec(&mut self) -> [&mut T; 14] {
|
#[allow(clippy::inconsistent_digit_grouping)]
|
||||||
|
pub fn get_mut(&mut self, group: usize) -> &mut T {
|
||||||
|
if group == 0 {
|
||||||
|
&mut self._0sat
|
||||||
|
} else if group == 10 {
|
||||||
|
&mut self.from_1sat_to_10sats
|
||||||
|
} else if group == 100 {
|
||||||
|
&mut self.from_10sats_to_100sats
|
||||||
|
} else if group == 1_000 {
|
||||||
|
&mut self.from_100sats_to_1_000sats
|
||||||
|
} else if group == 10_000 {
|
||||||
|
&mut self.from_1_000sats_to_10_000sats
|
||||||
|
} else if group == 100_000 {
|
||||||
|
&mut self.from_10_000sats_to_100_000sats
|
||||||
|
} else if group == 1_000_000 {
|
||||||
|
&mut self.from_100_000sats_to_1_000_000sats
|
||||||
|
} else if group == 10_000_000 {
|
||||||
|
&mut self.from_1_000_000sats_to_10_000_000sats
|
||||||
|
} else if group == 1_00_000_000 {
|
||||||
|
&mut self.from_10_000_000sats_to_1btc
|
||||||
|
} else if group == 10_00_000_000 {
|
||||||
|
&mut self.from_1btc_to_10btc
|
||||||
|
} else if group == 100_00_000_000 {
|
||||||
|
&mut self.from_10btc_to_100btc
|
||||||
|
} else if group == 1_000_00_000_000 {
|
||||||
|
&mut self.from_100btc_to_1_000btc
|
||||||
|
} else if group == 10_000_00_000_000 {
|
||||||
|
&mut self.from_1_000btc_to_10_000btc
|
||||||
|
} else if group == 100_000_00_000_000 {
|
||||||
|
&mut self.from_10_000btc_to_100_000btc
|
||||||
|
} else {
|
||||||
|
&mut self.from_100_000btc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_mut_vec(&mut self) -> [&mut T; 15] {
|
||||||
[
|
[
|
||||||
|
&mut self._0sat,
|
||||||
&mut self.from_1sat_to_10sats,
|
&mut self.from_1sat_to_10sats,
|
||||||
&mut self.from_10sats_to_100sats,
|
&mut self.from_10sats_to_100sats,
|
||||||
&mut self.from_100sats_to_1_000sats,
|
&mut self.from_100sats_to_1_000sats,
|
||||||
@@ -106,8 +160,9 @@ impl<T> OutputsBySize<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsBySize<(OutputFilter, T)> {
|
impl<T> OutputsBySize<(OutputFilter, T)> {
|
||||||
pub fn vecs(&self) -> [&T; 14] {
|
pub fn vecs(&self) -> [&T; 15] {
|
||||||
[
|
[
|
||||||
|
&self._0sat.1,
|
||||||
&self.from_1sat_to_10sats.1,
|
&self.from_1sat_to_10sats.1,
|
||||||
&self.from_10sats_to_100sats.1,
|
&self.from_10sats_to_100sats.1,
|
||||||
&self.from_100sats_to_1_000sats.1,
|
&self.from_100sats_to_1_000sats.1,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use brk_core::{OutputType, Sats};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
use crate::states::SupplyState;
|
use brk_core::OutputType;
|
||||||
|
|
||||||
use super::OutputFilter;
|
use super::OutputFilter;
|
||||||
|
|
||||||
@@ -16,24 +16,26 @@ pub struct OutputsBySpendableType<T> {
|
|||||||
pub p2tr: T,
|
pub p2tr: T,
|
||||||
pub p2a: T,
|
pub p2a: T,
|
||||||
pub unknown: T,
|
pub unknown: T,
|
||||||
|
pub empty: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsBySpendableType<T> {
|
impl<T> OutputsBySpendableType<T> {
|
||||||
pub fn get(&self, output_type: OutputType) -> &T {
|
// pub fn get(&self, output_type: OutputType) -> &T {
|
||||||
match output_type {
|
// match output_type {
|
||||||
OutputType::P2PK65 => &self.p2pk65,
|
// OutputType::P2PK65 => &self.p2pk65,
|
||||||
OutputType::P2PK33 => &self.p2pk33,
|
// OutputType::P2PK33 => &self.p2pk33,
|
||||||
OutputType::P2PKH => &self.p2pkh,
|
// OutputType::P2PKH => &self.p2pkh,
|
||||||
OutputType::P2MS => &self.p2ms,
|
// OutputType::P2MS => &self.p2ms,
|
||||||
OutputType::P2SH => &self.p2sh,
|
// OutputType::P2SH => &self.p2sh,
|
||||||
OutputType::P2WPKH => &self.p2wpkh,
|
// OutputType::P2WPKH => &self.p2wpkh,
|
||||||
OutputType::P2WSH => &self.p2wsh,
|
// OutputType::P2WSH => &self.p2wsh,
|
||||||
OutputType::P2TR => &self.p2tr,
|
// OutputType::P2TR => &self.p2tr,
|
||||||
OutputType::P2A => &self.p2a,
|
// OutputType::P2A => &self.p2a,
|
||||||
OutputType::Unknown => &self.unknown,
|
// OutputType::Unknown => &self.unknown,
|
||||||
_ => unreachable!(),
|
// OutputType::Empty => &self.empty,
|
||||||
}
|
// _ => unreachable!(),
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
||||||
match output_type {
|
match output_type {
|
||||||
@@ -47,26 +49,28 @@ impl<T> OutputsBySpendableType<T> {
|
|||||||
OutputType::P2TR => &mut self.p2tr,
|
OutputType::P2TR => &mut self.p2tr,
|
||||||
OutputType::P2A => &mut self.p2a,
|
OutputType::P2A => &mut self.p2a,
|
||||||
OutputType::Unknown => &mut self.unknown,
|
OutputType::Unknown => &mut self.unknown,
|
||||||
|
OutputType::Empty => &mut self.empty,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_vec(&self) -> [&T; 10] {
|
// pub fn as_vec(&self) -> [&T; 11] {
|
||||||
[
|
// [
|
||||||
&self.p2pk65,
|
// &self.p2pk65,
|
||||||
&self.p2pk33,
|
// &self.p2pk33,
|
||||||
&self.p2pkh,
|
// &self.p2pkh,
|
||||||
&self.p2ms,
|
// &self.p2ms,
|
||||||
&self.p2sh,
|
// &self.p2sh,
|
||||||
&self.p2wpkh,
|
// &self.p2wpkh,
|
||||||
&self.p2wsh,
|
// &self.p2wsh,
|
||||||
&self.p2tr,
|
// &self.p2tr,
|
||||||
&self.p2a,
|
// &self.p2a,
|
||||||
&self.unknown,
|
// &self.unknown,
|
||||||
]
|
// &self.empty,
|
||||||
}
|
// ]
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn as_mut_vec(&mut self) -> [&mut T; 10] {
|
pub fn as_mut_vec(&mut self) -> [&mut T; 11] {
|
||||||
[
|
[
|
||||||
&mut self.p2pk65,
|
&mut self.p2pk65,
|
||||||
&mut self.p2pk33,
|
&mut self.p2pk33,
|
||||||
@@ -78,10 +82,11 @@ impl<T> OutputsBySpendableType<T> {
|
|||||||
&mut self.p2tr,
|
&mut self.p2tr,
|
||||||
&mut self.p2a,
|
&mut self.p2a,
|
||||||
&mut self.unknown,
|
&mut self.unknown,
|
||||||
|
&mut self.empty,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_typed_vec(&self) -> [(OutputType, &T); 10] {
|
pub fn as_typed_vec(&self) -> [(OutputType, &T); 11] {
|
||||||
[
|
[
|
||||||
(OutputType::P2PK65, &self.p2pk65),
|
(OutputType::P2PK65, &self.p2pk65),
|
||||||
(OutputType::P2PK33, &self.p2pk33),
|
(OutputType::P2PK33, &self.p2pk33),
|
||||||
@@ -93,12 +98,13 @@ impl<T> OutputsBySpendableType<T> {
|
|||||||
(OutputType::P2TR, &self.p2tr),
|
(OutputType::P2TR, &self.p2tr),
|
||||||
(OutputType::P2A, &self.p2a),
|
(OutputType::P2A, &self.p2a),
|
||||||
(OutputType::Unknown, &self.unknown),
|
(OutputType::Unknown, &self.unknown),
|
||||||
|
(OutputType::Empty, &self.empty),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsBySpendableType<(OutputFilter, T)> {
|
impl<T> OutputsBySpendableType<(OutputFilter, T)> {
|
||||||
pub fn vecs(&self) -> [&T; 10] {
|
pub fn vecs(&self) -> [&T; 11] {
|
||||||
[
|
[
|
||||||
&self.p2pk65.1,
|
&self.p2pk65.1,
|
||||||
&self.p2pk33.1,
|
&self.p2pk33.1,
|
||||||
@@ -110,6 +116,7 @@ impl<T> OutputsBySpendableType<(OutputFilter, T)> {
|
|||||||
&self.p2tr.1,
|
&self.p2tr.1,
|
||||||
&self.p2a.1,
|
&self.p2a.1,
|
||||||
&self.unknown.1,
|
&self.unknown.1,
|
||||||
|
&self.empty.1,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,16 +134,48 @@ impl<T> From<OutputsBySpendableType<T>> for OutputsBySpendableType<(OutputFilter
|
|||||||
p2tr: (OutputFilter::Type(OutputType::P2TR), value.p2tr),
|
p2tr: (OutputFilter::Type(OutputType::P2TR), value.p2tr),
|
||||||
p2a: (OutputFilter::Type(OutputType::P2A), value.p2a),
|
p2a: (OutputFilter::Type(OutputType::P2A), value.p2a),
|
||||||
unknown: (OutputFilter::Type(OutputType::Unknown), value.unknown),
|
unknown: (OutputFilter::Type(OutputType::Unknown), value.unknown),
|
||||||
|
empty: (OutputFilter::Type(OutputType::Empty), value.empty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputsBySpendableType<(SupplyState, Vec<Sats>)> {
|
impl<T> Add for OutputsBySpendableType<T>
|
||||||
pub fn reduce(&self) -> SupplyState {
|
where
|
||||||
let mut supply_state = SupplyState::default();
|
T: Add<Output = T>,
|
||||||
self.as_vec().iter().for_each(|(supply_state_, _)| {
|
{
|
||||||
supply_state += supply_state_;
|
type Output = Self;
|
||||||
});
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
supply_state
|
Self {
|
||||||
|
p2pk65: self.p2pk65 + rhs.p2pk65,
|
||||||
|
p2pk33: self.p2pk33 + rhs.p2pk33,
|
||||||
|
p2pkh: self.p2pkh + rhs.p2pkh,
|
||||||
|
p2ms: self.p2ms + rhs.p2ms,
|
||||||
|
p2sh: self.p2sh + rhs.p2sh,
|
||||||
|
p2wpkh: self.p2wpkh + rhs.p2wpkh,
|
||||||
|
p2wsh: self.p2wsh + rhs.p2wsh,
|
||||||
|
p2tr: self.p2tr + rhs.p2tr,
|
||||||
|
p2a: self.p2a + rhs.p2a,
|
||||||
|
unknown: self.unknown + rhs.unknown,
|
||||||
|
empty: self.empty + rhs.empty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AddAssign for OutputsBySpendableType<T>
|
||||||
|
where
|
||||||
|
T: AddAssign,
|
||||||
|
{
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.p2pk65 += rhs.p2pk65;
|
||||||
|
self.p2pk33 += rhs.p2pk33;
|
||||||
|
self.p2pkh += rhs.p2pkh;
|
||||||
|
self.p2ms += rhs.p2ms;
|
||||||
|
self.p2sh += rhs.p2sh;
|
||||||
|
self.p2wpkh += rhs.p2wpkh;
|
||||||
|
self.p2wsh += rhs.p2wsh;
|
||||||
|
self.p2tr += rhs.p2tr;
|
||||||
|
self.p2a += rhs.p2a;
|
||||||
|
self.unknown += rhs.unknown;
|
||||||
|
self.empty += rhs.empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
use brk_core::OutputType;
|
use brk_core::OutputType;
|
||||||
|
|
||||||
use super::{OutputsBySpendableType, OutputsByUnspendableType};
|
use super::{OutputsBySpendableType, OutputsByUnspendableType};
|
||||||
@@ -9,22 +11,22 @@ pub struct OutputsByType<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsByType<T> {
|
impl<T> OutputsByType<T> {
|
||||||
// pub fn get(&self, output_type: OutputType) -> &T {
|
pub fn get(&self, output_type: OutputType) -> &T {
|
||||||
// match output_type {
|
match output_type {
|
||||||
// OutputType::P2PK65 => &self.spendable.p2pk65,
|
OutputType::P2PK65 => &self.spendable.p2pk65,
|
||||||
// OutputType::P2PK33 => &self.spendable.p2pk33,
|
OutputType::P2PK33 => &self.spendable.p2pk33,
|
||||||
// OutputType::P2PKH => &self.spendable.p2pkh,
|
OutputType::P2PKH => &self.spendable.p2pkh,
|
||||||
// OutputType::P2MS => &self.spendable.p2ms,
|
OutputType::P2MS => &self.spendable.p2ms,
|
||||||
// OutputType::P2SH => &self.spendable.p2sh,
|
OutputType::P2SH => &self.spendable.p2sh,
|
||||||
// OutputType::P2WPKH => &self.spendable.p2wpkh,
|
OutputType::P2WPKH => &self.spendable.p2wpkh,
|
||||||
// OutputType::P2WSH => &self.spendable.p2wsh,
|
OutputType::P2WSH => &self.spendable.p2wsh,
|
||||||
// OutputType::P2TR => &self.spendable.p2tr,
|
OutputType::P2TR => &self.spendable.p2tr,
|
||||||
// OutputType::P2A => &self.spendable.p2a,
|
OutputType::P2A => &self.spendable.p2a,
|
||||||
// OutputType::OpReturn => &self.unspendable.op_return,
|
OutputType::Empty => &self.spendable.empty,
|
||||||
// OutputType::Empty => &self.unspendable.empty,
|
OutputType::Unknown => &self.spendable.unknown,
|
||||||
// OutputType::Unknown => &self.unspendable.unknown,
|
OutputType::OpReturn => &self.unspendable.op_return,
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
||||||
match output_type {
|
match output_type {
|
||||||
@@ -38,18 +40,18 @@ impl<T> OutputsByType<T> {
|
|||||||
OutputType::P2TR => &mut self.spendable.p2tr,
|
OutputType::P2TR => &mut self.spendable.p2tr,
|
||||||
OutputType::P2A => &mut self.spendable.p2a,
|
OutputType::P2A => &mut self.spendable.p2a,
|
||||||
OutputType::Unknown => &mut self.spendable.unknown,
|
OutputType::Unknown => &mut self.spendable.unknown,
|
||||||
|
OutputType::Empty => &mut self.spendable.empty,
|
||||||
OutputType::OpReturn => &mut self.unspendable.op_return,
|
OutputType::OpReturn => &mut self.unspendable.op_return,
|
||||||
OutputType::Empty => &mut self.unspendable.empty,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_vec(&self) -> Vec<&T> {
|
// pub fn as_vec(&self) -> Vec<&T> {
|
||||||
self.spendable
|
// self.spendable
|
||||||
.as_vec()
|
// .as_vec()
|
||||||
.into_iter()
|
// .into_iter()
|
||||||
.chain(self.unspendable.as_vec())
|
// .chain(self.unspendable.as_vec())
|
||||||
.collect::<Vec<_>>()
|
// .collect::<Vec<_>>()
|
||||||
}
|
// }
|
||||||
|
|
||||||
// pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
// pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
||||||
// self.spendable
|
// self.spendable
|
||||||
@@ -59,3 +61,26 @@ impl<T> OutputsByType<T> {
|
|||||||
// .collect::<Vec<_>>()
|
// .collect::<Vec<_>>()
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Add for OutputsByType<T>
|
||||||
|
where
|
||||||
|
T: Add<Output = T>,
|
||||||
|
{
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
spendable: self.spendable + rhs.spendable,
|
||||||
|
unspendable: self.unspendable + rhs.unspendable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AddAssign for OutputsByType<T>
|
||||||
|
where
|
||||||
|
T: AddAssign,
|
||||||
|
{
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.spendable += rhs.spendable;
|
||||||
|
self.unspendable += rhs.unspendable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,47 +1,33 @@
|
|||||||
// use brk_core::OutputType;
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct OutputsByUnspendableType<T> {
|
pub struct OutputsByUnspendableType<T> {
|
||||||
pub op_return: T,
|
pub op_return: T,
|
||||||
pub empty: T,
|
|
||||||
// pub unknown: T,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> OutputsByUnspendableType<T> {
|
impl<T> OutputsByUnspendableType<T> {
|
||||||
// pub fn get(&self, output_type: OutputType) -> &T {
|
pub fn as_vec(&self) -> [&T; 1] {
|
||||||
// match output_type {
|
[&self.op_return]
|
||||||
// OutputType::OpReturn => &self.op_return,
|
}
|
||||||
// OutputType::Empty => &self.empty,
|
}
|
||||||
// OutputType::Unknown => &self.unknown,
|
|
||||||
// _ => unreachable!(),
|
impl<T> Add for OutputsByUnspendableType<T>
|
||||||
// }
|
where
|
||||||
// }
|
T: Add<Output = T>,
|
||||||
|
{
|
||||||
// pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
type Output = Self;
|
||||||
// match output_type {
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
// OutputType::OpReturn => &mut self.op_return,
|
Self {
|
||||||
// OutputType::Empty => &mut self.empty,
|
op_return: self.op_return + rhs.op_return,
|
||||||
// OutputType::Unknown => &mut self.unknown,
|
}
|
||||||
// _ => unreachable!(),
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
impl<T> AddAssign for OutputsByUnspendableType<T>
|
||||||
// pub fn to_unspendable_vec(&self) -> Vec<&T> {
|
where
|
||||||
// OutputType::as_vec()
|
T: AddAssign,
|
||||||
// .into_iter()
|
{
|
||||||
// .map(|t| (self.get(t)))
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
// .collect::<Vec<_>>()
|
self.op_return += rhs.op_return;
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn as_vec(&self) -> [&T; 2] {
|
|
||||||
[
|
|
||||||
&self.op_return,
|
|
||||||
&self.empty,
|
|
||||||
// &self.unknown
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn as_mut_vec(&mut self) -> [&mut T; 3] {
|
|
||||||
// [&mut self.op_return, &mut self.empty, &mut self.unknown]
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use brk_core::{HalvingEpoch, OutputType, Sats};
|
use brk_core::{HalvingEpoch, OutputType};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum OutputFilter {
|
pub enum OutputFilter {
|
||||||
@@ -8,7 +8,7 @@ pub enum OutputFilter {
|
|||||||
To(usize),
|
To(usize),
|
||||||
Range(Range<usize>),
|
Range(Range<usize>),
|
||||||
From(usize),
|
From(usize),
|
||||||
Size(Range<Sats>),
|
Size,
|
||||||
Epoch(HalvingEpoch),
|
Epoch(HalvingEpoch),
|
||||||
Type(OutputType),
|
Type(OutputType),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use brk_vec::StoredIndex;
|
|||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::{collections::BTreeMap, ops::ControlFlow};
|
use std::{collections::BTreeMap, ops::ControlFlow};
|
||||||
|
|
||||||
use brk_core::{Dollars, HalvingEpoch, Height, Sats, Timestamp};
|
use brk_core::{Dollars, HalvingEpoch, Height, Timestamp};
|
||||||
|
|
||||||
mod by_epoch;
|
mod by_epoch;
|
||||||
mod by_from;
|
mod by_from;
|
||||||
@@ -30,7 +30,7 @@ pub use filter::*;
|
|||||||
|
|
||||||
use crate::vecs;
|
use crate::vecs;
|
||||||
|
|
||||||
use super::{BlockState, SupplyState};
|
use super::{BlockState, Transacted};
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Outputs<T> {
|
pub struct Outputs<T> {
|
||||||
@@ -38,12 +38,12 @@ pub struct Outputs<T> {
|
|||||||
pub by_term: OutputsByTerm<T>,
|
pub by_term: OutputsByTerm<T>,
|
||||||
// pub by_up_to: OutputsByUpTo<T>,
|
// pub by_up_to: OutputsByUpTo<T>,
|
||||||
pub by_from: OutputsByFrom<T>,
|
pub by_from: OutputsByFrom<T>,
|
||||||
// pub by_range: OutputsByRange<T>,
|
pub by_range: OutputsByRange<T>,
|
||||||
pub by_epoch: OutputsByEpoch<T>,
|
pub by_epoch: OutputsByEpoch<T>,
|
||||||
|
pub by_type: OutputsBySpendableType<T>,
|
||||||
pub by_size: OutputsBySize<T>,
|
pub by_size: OutputsBySize<T>,
|
||||||
// // Needs whole UTXO set, TODO later
|
// // Needs whole UTXO set, TODO later
|
||||||
// // pub by_value: OutputsByValue<T>,
|
// // pub by_value: OutputsByValue<T>,
|
||||||
pub by_spendable_type: OutputsBySpendableType<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Outputs<T> {
|
impl<T> Outputs<T> {
|
||||||
@@ -53,11 +53,11 @@ impl<T> Outputs<T> {
|
|||||||
.chain(self.by_term.as_mut_vec())
|
.chain(self.by_term.as_mut_vec())
|
||||||
// .chain(self.by_up_to.as_mut_vec())
|
// .chain(self.by_up_to.as_mut_vec())
|
||||||
.chain(self.by_from.as_mut_vec())
|
.chain(self.by_from.as_mut_vec())
|
||||||
// .chain(self.by_range.as_mut_vec())
|
.chain(self.by_range.as_mut_vec())
|
||||||
.chain(self.by_epoch.as_mut_vec())
|
.chain(self.by_epoch.as_mut_vec())
|
||||||
.chain(self.by_size.as_mut_vec())
|
.chain(self.by_size.as_mut_vec())
|
||||||
|
.chain(self.by_type.as_mut_vec())
|
||||||
// // .chain(self.by_value.as_mut_vec())
|
// // .chain(self.by_value.as_mut_vec())
|
||||||
.chain(self.by_spendable_type.as_mut_vec())
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
// .chain(self.by_up_to.as_mut_vec())
|
// .chain(self.by_up_to.as_mut_vec())
|
||||||
.chain(self.by_from.as_mut_vec())
|
.chain(self.by_from.as_mut_vec())
|
||||||
// .chain(self.by_range.as_mut_vec())
|
.chain(self.by_range.as_mut_vec())
|
||||||
.for_each(|(filter, v)| {
|
.for_each(|(filter, v)| {
|
||||||
let state = &mut v.state;
|
let state = &mut v.state;
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
OutputFilter::Range(range) => range.contains(&days_old),
|
OutputFilter::Range(range) => range.contains(&days_old),
|
||||||
OutputFilter::All
|
OutputFilter::All
|
||||||
| OutputFilter::Epoch(_)
|
| OutputFilter::Epoch(_)
|
||||||
| OutputFilter::Size(_)
|
| OutputFilter::Size
|
||||||
| OutputFilter::Type(_) => unreachable!(),
|
| OutputFilter::Type(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -98,12 +98,14 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
.timestamp
|
.timestamp
|
||||||
.difference_in_days_between(prev_timestamp);
|
.difference_in_days_between(prev_timestamp);
|
||||||
let days_old = block_state.timestamp.difference_in_days_between(timestamp);
|
let days_old = block_state.timestamp.difference_in_days_between(timestamp);
|
||||||
|
|
||||||
if prev_days_old == days_old {
|
if prev_days_old == days_old {
|
||||||
return ControlFlow::Continue(());
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let is = check_days_old(days_old);
|
let is = check_days_old(days_old);
|
||||||
let was = check_days_old(prev_days_old);
|
let was = check_days_old(prev_days_old);
|
||||||
|
|
||||||
if is && !was {
|
if is && !was {
|
||||||
state.increment(&block_state.supply, block_state.price);
|
state.increment(&block_state.supply, block_state.price);
|
||||||
} else if was && !is {
|
} else if was && !is {
|
||||||
@@ -117,7 +119,7 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
|
|
||||||
pub fn send(
|
pub fn send(
|
||||||
&mut self,
|
&mut self,
|
||||||
height_to_sent: BTreeMap<Height, OutputsByType<(SupplyState, Vec<Sats>)>>,
|
height_to_sent: BTreeMap<Height, Transacted>,
|
||||||
chain_state: &[BlockState],
|
chain_state: &[BlockState],
|
||||||
) {
|
) {
|
||||||
let mut time_based_vecs = self
|
let mut time_based_vecs = self
|
||||||
@@ -126,58 +128,21 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
// .chain(self.by_up_to.as_mut_vec())
|
// .chain(self.by_up_to.as_mut_vec())
|
||||||
.chain(self.by_from.as_mut_vec())
|
.chain(self.by_from.as_mut_vec())
|
||||||
// .chain(self.by_range.as_mut_vec())
|
.chain(self.by_range.as_mut_vec())
|
||||||
.chain(self.by_epoch.as_mut_vec())
|
.chain(self.by_epoch.as_mut_vec())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let last_timestamp = chain_state.last().unwrap().timestamp;
|
let last_timestamp = chain_state.last().unwrap().timestamp;
|
||||||
|
|
||||||
height_to_sent.into_iter().for_each(|(height, by_type)| {
|
height_to_sent.into_iter().for_each(|(height, sent)| {
|
||||||
let by_spendable_type = by_type.spendable;
|
|
||||||
|
|
||||||
let block_state = chain_state.get(height.unwrap_to_usize()).unwrap();
|
let block_state = chain_state.get(height.unwrap_to_usize()).unwrap();
|
||||||
let price = block_state.price;
|
let price = block_state.price;
|
||||||
let supply_state = by_spendable_type.reduce();
|
|
||||||
|
|
||||||
let days_old = block_state
|
let days_old = block_state
|
||||||
.timestamp
|
.timestamp
|
||||||
.difference_in_days_between(last_timestamp);
|
.difference_in_days_between(last_timestamp);
|
||||||
|
|
||||||
self.all.1.state.decrement(&supply_state, price);
|
self.all.1.state.decrement(&sent.spendable_supply, price);
|
||||||
|
|
||||||
by_spendable_type.as_typed_vec().into_iter().for_each(
|
|
||||||
|(output_type, (supply_state, _))| {
|
|
||||||
self.by_spendable_type
|
|
||||||
.get_mut(output_type)
|
|
||||||
.1
|
|
||||||
.state
|
|
||||||
.decrement(supply_state, price)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
by_spendable_type
|
|
||||||
.as_vec()
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|(_, sats_received)| sats_received.iter())
|
|
||||||
.for_each(|sats| {
|
|
||||||
let sats = *sats;
|
|
||||||
self.by_size
|
|
||||||
.as_mut_vec()
|
|
||||||
.iter_mut()
|
|
||||||
.filter(|(filter, _)| match filter {
|
|
||||||
OutputFilter::Size(range) => range.contains(&sats),
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
.for_each(|(_, vec)| {
|
|
||||||
vec.state.decrement(
|
|
||||||
&SupplyState {
|
|
||||||
utxos: 1,
|
|
||||||
value: sats,
|
|
||||||
},
|
|
||||||
price,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
time_based_vecs
|
time_based_vecs
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@@ -189,18 +154,31 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.for_each(|(_, vecs)| {
|
.for_each(|(_, vecs)| {
|
||||||
vecs.state.decrement(&supply_state, price);
|
vecs.state.decrement(&sent.spendable_supply, price);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sent.by_type.spendable.as_typed_vec().into_iter().for_each(
|
||||||
|
|(output_type, supply_state)| {
|
||||||
|
self.by_type
|
||||||
|
.get_mut(output_type)
|
||||||
|
.1
|
||||||
|
.state
|
||||||
|
.decrement(supply_state, price)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sent.by_size.into_iter().for_each(|(group, supply_state)| {
|
||||||
|
self.by_size
|
||||||
|
.get_mut(group)
|
||||||
|
.1
|
||||||
|
.state
|
||||||
|
.decrement(&supply_state, price);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive(
|
pub fn receive(&mut self, received: Transacted, height: Height, price: Option<Dollars>) {
|
||||||
&mut self,
|
let supply_state = received.spendable_supply;
|
||||||
received: OutputsByType<(SupplyState, Vec<Sats>)>,
|
|
||||||
height: Height,
|
|
||||||
price: Option<Dollars>,
|
|
||||||
) {
|
|
||||||
let supply_state = received.spendable.reduce();
|
|
||||||
|
|
||||||
[
|
[
|
||||||
&mut self.all.1,
|
&mut self.all.1,
|
||||||
@@ -214,34 +192,7 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
v.state.increment(&supply_state, price);
|
v.state.increment(&supply_state, price);
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut by_size = self.by_size.as_mut_vec();
|
self.by_type
|
||||||
|
|
||||||
received
|
|
||||||
.spendable
|
|
||||||
.as_vec()
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|(_, sats_received)| sats_received.iter())
|
|
||||||
.for_each(|sats| {
|
|
||||||
let sats = *sats;
|
|
||||||
|
|
||||||
by_size
|
|
||||||
.iter_mut()
|
|
||||||
.filter(|(filter, _)| match filter {
|
|
||||||
OutputFilter::Size(range) => range.contains(&sats),
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
.for_each(|(_, vec)| {
|
|
||||||
vec.state.increment(
|
|
||||||
&SupplyState {
|
|
||||||
utxos: 1,
|
|
||||||
value: sats,
|
|
||||||
},
|
|
||||||
price,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
self.by_spendable_type
|
|
||||||
.as_mut_vec()
|
.as_mut_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|(filter, vecs)| {
|
.for_each(|(filter, vecs)| {
|
||||||
@@ -250,7 +201,18 @@ impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
vecs.state
|
vecs.state
|
||||||
.increment(&received.spendable.get(output_type).0, price)
|
.increment(received.by_type.get(output_type), price)
|
||||||
|
});
|
||||||
|
|
||||||
|
received
|
||||||
|
.by_size
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|(group, supply_state)| {
|
||||||
|
self.by_size
|
||||||
|
.get_mut(group)
|
||||||
|
.1
|
||||||
|
.state
|
||||||
|
.increment(&supply_state, price);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,11 +224,11 @@ impl<T> Outputs<(OutputFilter, T)> {
|
|||||||
.chain(self.by_term.vecs())
|
.chain(self.by_term.vecs())
|
||||||
// .chain(self.by_up_to.vecs())
|
// .chain(self.by_up_to.vecs())
|
||||||
.chain(self.by_from.vecs())
|
.chain(self.by_from.vecs())
|
||||||
// .chain(self.by_range.vecs())
|
.chain(self.by_range.vecs())
|
||||||
.chain(self.by_epoch.vecs())
|
.chain(self.by_epoch.vecs())
|
||||||
.chain(self.by_size.vecs())
|
.chain(self.by_size.vecs())
|
||||||
// // .chain(self.by_value.vecs())
|
// // .chain(self.by_value.vecs())
|
||||||
.chain(self.by_spendable_type.vecs())
|
.chain(self.by_type.vecs())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,12 +240,12 @@ impl<T> From<Outputs<T>> for Outputs<(OutputFilter, T)> {
|
|||||||
by_term: OutputsByTerm::from(value.by_term),
|
by_term: OutputsByTerm::from(value.by_term),
|
||||||
// by_up_to: OutputsByUpTo::from(value.by_up_to),
|
// by_up_to: OutputsByUpTo::from(value.by_up_to),
|
||||||
by_from: OutputsByFrom::from(value.by_from),
|
by_from: OutputsByFrom::from(value.by_from),
|
||||||
// by_range: OutputsByRange::from(value.by_range),
|
by_range: OutputsByRange::from(value.by_range),
|
||||||
by_epoch: OutputsByEpoch::from(value.by_epoch),
|
by_epoch: OutputsByEpoch::from(value.by_epoch),
|
||||||
by_size: OutputsBySize::from(value.by_size),
|
by_size: OutputsBySize::from(value.by_size),
|
||||||
// // Needs whole UTXO set, TODO later
|
// // Needs whole UTXO set, TODO later
|
||||||
// // by_value: OutputsByValue<T>,
|
// // by_value: OutputsByValue<T>,
|
||||||
by_spendable_type: OutputsBySpendableType::from(value.by_spendable_type),
|
by_type: OutputsBySpendableType::from(value.by_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,61 @@
|
|||||||
use brk_core::Dollars;
|
use brk_core::{Bitcoin, CheckedSub, Dollars};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
use super::SupplyState;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct RealizedState {
|
pub struct RealizedState {
|
||||||
realized_profit: Dollars,
|
pub realized_cap: Dollars,
|
||||||
realized_loss: Dollars,
|
// pub realized_profit: Dollars,
|
||||||
value_created: Dollars,
|
// pub realized_loss: Dollars,
|
||||||
adjusted_value_created: Dollars,
|
// pub value_created: Dollars,
|
||||||
value_destroyed: Dollars,
|
// pub adjusted_value_created: Dollars,
|
||||||
adjusted_value_destroyed: Dollars,
|
// pub value_destroyed: Dollars,
|
||||||
|
// pub adjusted_value_destroyed: Dollars,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RealizedState {
|
||||||
|
pub const NAN: Self = Self {
|
||||||
|
realized_cap: Dollars::NAN,
|
||||||
|
// realized_profit: Dollars::NAN,
|
||||||
|
// realized_loss: Dollars::NAN,
|
||||||
|
// value_created: Dollars::NAN,
|
||||||
|
// adjusted_value_created: Dollars::NAN,
|
||||||
|
// value_destroyed: Dollars::NAN,
|
||||||
|
// adjusted_value_destroyed: Dollars::NAN,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn increment(&mut self, supply_state: &SupplyState, price: Dollars) {
|
||||||
|
if supply_state.value.is_not_zero() {
|
||||||
|
if self.realized_cap == Dollars::NAN {
|
||||||
|
self.realized_cap = Dollars::ZERO;
|
||||||
|
}
|
||||||
|
self.realized_cap += price * Bitcoin::from(supply_state.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if self.realized_profit == Dollars::NAN {
|
||||||
|
// self.realized_profit = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
// if self.realized_loss == Dollars::NAN {
|
||||||
|
// self.realized_loss = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
// if self.value_created == Dollars::NAN {
|
||||||
|
// self.value_created = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
// if self.adjusted_value_created == Dollars::NAN {
|
||||||
|
// self.adjusted_value_created = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
// if self.value_destroyed == Dollars::NAN {
|
||||||
|
// self.value_destroyed = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
// if self.adjusted_value_destroyed == Dollars::NAN {
|
||||||
|
// self.adjusted_value_destroyed = Dollars::ZERO;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrement(&mut self, supply_state: &SupplyState, price: Dollars) {
|
||||||
|
self.realized_cap = self
|
||||||
|
.realized_cap
|
||||||
|
.checked_sub(price * Bitcoin::from(supply_state.value))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ impl Add<SupplyState> for SupplyState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AddAssign<SupplyState> for SupplyState {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
*self += &rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AddAssign<&SupplyState> for SupplyState {
|
impl AddAssign<&SupplyState> for SupplyState {
|
||||||
fn add_assign(&mut self, rhs: &Self) {
|
fn add_assign(&mut self, rhs: &Self) {
|
||||||
self.utxos += rhs.utxos;
|
self.utxos += rhs.utxos;
|
||||||
|
|||||||
100
crates/brk_computer/src/states/transacted.rs
Normal file
100
crates/brk_computer/src/states/transacted.rs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
mem,
|
||||||
|
ops::{Add, AddAssign},
|
||||||
|
};
|
||||||
|
|
||||||
|
use brk_core::{OutputType, Sats};
|
||||||
|
|
||||||
|
use super::{OutputsByType, SupplyState};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Transacted {
|
||||||
|
pub spendable_supply: SupplyState,
|
||||||
|
pub by_type: OutputsByType<SupplyState>,
|
||||||
|
pub by_size: BTreeMap<usize, SupplyState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transacted {
|
||||||
|
#[allow(clippy::inconsistent_digit_grouping)]
|
||||||
|
pub fn iterate(&mut self, value: Sats, _type: OutputType) {
|
||||||
|
let supply = SupplyState { utxos: 1, value };
|
||||||
|
|
||||||
|
*self.by_type.get_mut(_type) += &supply;
|
||||||
|
|
||||||
|
if _type.is_unspendable() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.spendable_supply += &supply;
|
||||||
|
|
||||||
|
let _value = usize::from(value);
|
||||||
|
|
||||||
|
// Need to be in sync with by_size !! but plenty fast (I think)
|
||||||
|
if _value == 0 {
|
||||||
|
*self.by_size.entry(0).or_default() += &supply;
|
||||||
|
} else if _value < 10 {
|
||||||
|
*self.by_size.entry(1).or_default() += &supply;
|
||||||
|
} else if _value < 100 {
|
||||||
|
*self.by_size.entry(10).or_default() += &supply;
|
||||||
|
} else if _value < 1_000 {
|
||||||
|
*self.by_size.entry(100).or_default() += &supply;
|
||||||
|
} else if _value < 10_000 {
|
||||||
|
*self.by_size.entry(1_000).or_default() += &supply;
|
||||||
|
} else if _value < 100_000 {
|
||||||
|
*self.by_size.entry(10_000).or_default() += &supply;
|
||||||
|
} else if _value < 1_000_000 {
|
||||||
|
*self.by_size.entry(100_000).or_default() += &supply;
|
||||||
|
} else if _value < 10_000_000 {
|
||||||
|
*self.by_size.entry(1_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 1_00_000_000 {
|
||||||
|
*self.by_size.entry(10_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 10_00_000_000 {
|
||||||
|
*self.by_size.entry(1_00_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 100_00_000_000 {
|
||||||
|
*self.by_size.entry(10_00_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 1_000_00_000_000 {
|
||||||
|
*self.by_size.entry(100_00_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 10_000_00_000_000 {
|
||||||
|
*self.by_size.entry(1_000_00_000_000).or_default() += &supply;
|
||||||
|
} else if _value < 100_000_00_000_000 {
|
||||||
|
*self.by_size.entry(10_000_00_000_000).or_default() += &supply;
|
||||||
|
} else {
|
||||||
|
*self.by_size.entry(100_000_00_000_000).or_default() += &supply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_by_size(
|
||||||
|
first: BTreeMap<usize, SupplyState>,
|
||||||
|
second: BTreeMap<usize, SupplyState>,
|
||||||
|
) -> BTreeMap<usize, SupplyState> {
|
||||||
|
let (mut source, to_consume) = if first.len() > second.len() {
|
||||||
|
(first, second)
|
||||||
|
} else {
|
||||||
|
(second, first)
|
||||||
|
};
|
||||||
|
to_consume.into_iter().for_each(|(k, v)| {
|
||||||
|
*source.entry(k).or_default() += &v;
|
||||||
|
});
|
||||||
|
source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Transacted {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
spendable_supply: self.spendable_supply + rhs.spendable_supply,
|
||||||
|
by_type: self.by_type + rhs.by_type,
|
||||||
|
by_size: Self::merge_by_size(self.by_size, rhs.by_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for Transacted {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.by_size = Self::merge_by_size(mem::take(&mut self.by_size), rhs.by_size);
|
||||||
|
self.spendable_supply += &rhs.spendable_supply;
|
||||||
|
self.by_type += rhs.by_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -405,6 +405,7 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedVecsFromTxindex<Dollars> {
|
impl ComputedVecsFromTxindex<Dollars> {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn compute_rest_from_bitcoin(
|
pub fn compute_rest_from_bitcoin(
|
||||||
&mut self,
|
&mut self,
|
||||||
indexer: &Indexer,
|
indexer: &Indexer,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use brk_vec::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
states::CohortState,
|
states::{CohortState, RealizedState},
|
||||||
vecs::{
|
vecs::{
|
||||||
Indexes, fetched,
|
Indexes, fetched,
|
||||||
grouped::{
|
grouped::{
|
||||||
@@ -55,7 +55,7 @@ impl Vecs {
|
|||||||
|
|
||||||
let mut state = CohortState::default();
|
let mut state = CohortState::default();
|
||||||
if compute_dollars {
|
if compute_dollars {
|
||||||
state.realized_cap = Some(Dollars::ZERO);
|
state.realized = Some(RealizedState::NAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -169,11 +169,9 @@ impl Vecs {
|
|||||||
.unwrap_get_inner(prev_height);
|
.unwrap_get_inner(prev_height);
|
||||||
|
|
||||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
||||||
self.state.realized_cap = Some(
|
self.state.realized.as_mut().unwrap().realized_cap = height_to_realized_cap
|
||||||
height_to_realized_cap
|
.into_iter()
|
||||||
.into_iter()
|
.unwrap_get_inner(prev_height);
|
||||||
.unwrap_get_inner(prev_height),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,10 +213,14 @@ impl Vecs {
|
|||||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
||||||
height_to_realized_cap.forced_push_at(
|
height_to_realized_cap.forced_push_at(
|
||||||
height,
|
height,
|
||||||
self.state.realized_cap.unwrap_or_else(|| {
|
self.state
|
||||||
dbg!(&self.state);
|
.realized
|
||||||
panic!();
|
.as_ref()
|
||||||
}),
|
.unwrap_or_else(|| {
|
||||||
|
dbg!(&self.state);
|
||||||
|
panic!();
|
||||||
|
})
|
||||||
|
.realized_cap,
|
||||||
exit,
|
exit,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
use std::{cmp::Ordering, collections::BTreeMap, mem, path::Path, thread};
|
use std::{cmp::Ordering, collections::BTreeMap, mem, path::Path, thread};
|
||||||
|
|
||||||
use brk_core::{Height, InputIndex, OutputIndex, Sats};
|
use brk_core::{Height, InputIndex, OutputIndex, OutputType, Sats};
|
||||||
use brk_exit::Exit;
|
use brk_exit::Exit;
|
||||||
use brk_indexer::Indexer;
|
use brk_indexer::Indexer;
|
||||||
use brk_vec::{
|
use brk_vec::{
|
||||||
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Compressed, Computation, EagerVec,
|
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Compressed, Computation, EagerVec,
|
||||||
GenericStoredVec, StoredIndex, StoredVec, VecIterator, Version,
|
GenericStoredVec, StoredIndex, StoredVec, UnsafeSlice, VecIterator, Version,
|
||||||
};
|
};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use crate::states::{
|
use crate::states::{
|
||||||
BlockState, OutputFilter, Outputs, OutputsByEpoch, OutputsByFrom, OutputsByRange,
|
BlockState, OutputFilter, Outputs, OutputsByEpoch, OutputsByFrom, OutputsByRange,
|
||||||
OutputsBySize, OutputsBySpendableType, OutputsByTerm, OutputsByType, OutputsByUpTo,
|
OutputsBySize, OutputsBySpendableType, OutputsByTerm, SupplyState, Transacted,
|
||||||
ReceivedBlockStateData, SupplyState,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -23,7 +23,7 @@ use super::{
|
|||||||
|
|
||||||
pub mod cohort;
|
pub mod cohort;
|
||||||
|
|
||||||
const VERSION: Version = Version::new(99);
|
const VERSION: Version = Version::new(999);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Vecs {
|
pub struct Vecs {
|
||||||
@@ -32,6 +32,8 @@ pub struct Vecs {
|
|||||||
// cointime,...
|
// cointime,...
|
||||||
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
|
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
|
||||||
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
||||||
|
// pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
||||||
|
// pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||||
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,104 +393,104 @@ impl Vecs {
|
|||||||
fetched,
|
fetched,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
// by_range: OutputsByRange {
|
by_range: OutputsByRange {
|
||||||
// _1d_to_1w: cohort::Vecs::forced_import(
|
_1d_to_1w: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_1d_to_1w"),
|
Some("from_1d_to_1w"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _1w_to_1m: cohort::Vecs::forced_import(
|
_1w_to_1m: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_1w_to_1m"),
|
Some("from_1w_to_1m"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _1m_to_3m: cohort::Vecs::forced_import(
|
_1m_to_3m: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_1m_to_3m"),
|
Some("from_1m_to_3m"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _3m_to_6m: cohort::Vecs::forced_import(
|
_3m_to_6m: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_3m_to_6m"),
|
Some("from_3m_to_6m"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _6m_to_1y: cohort::Vecs::forced_import(
|
_6m_to_1y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_6m_to_1y"),
|
Some("from_6m_to_1y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _1y_to_2y: cohort::Vecs::forced_import(
|
_1y_to_2y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_1y_to_2y"),
|
Some("from_1y_to_2y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _2y_to_3y: cohort::Vecs::forced_import(
|
_2y_to_3y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_2y_to_3y"),
|
Some("from_2y_to_3y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _3y_to_4y: cohort::Vecs::forced_import(
|
_3y_to_4y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_3y_to_4y"),
|
Some("from_3y_to_4y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _4y_to_5y: cohort::Vecs::forced_import(
|
_4y_to_5y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_4y_to_5y"),
|
Some("from_4y_to_5y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _5y_to_7y: cohort::Vecs::forced_import(
|
_5y_to_7y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_5y_to_7y"),
|
Some("from_5y_to_7y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _7y_to_10y: cohort::Vecs::forced_import(
|
_7y_to_10y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_7y_to_10y"),
|
Some("from_7y_to_10y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// _10y_to_15y: cohort::Vecs::forced_import(
|
_10y_to_15y: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("from_10y_to_15y"),
|
Some("from_10y_to_15y"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
// },
|
},
|
||||||
by_epoch: OutputsByEpoch {
|
by_epoch: OutputsByEpoch {
|
||||||
_0: cohort::Vecs::forced_import(
|
_0: cohort::Vecs::forced_import(
|
||||||
path,
|
path,
|
||||||
@@ -532,6 +534,14 @@ impl Vecs {
|
|||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
by_size: OutputsBySize {
|
by_size: OutputsBySize {
|
||||||
|
_0sat: cohort::Vecs::forced_import(
|
||||||
|
path,
|
||||||
|
Some("0sat"),
|
||||||
|
_computation,
|
||||||
|
compressed,
|
||||||
|
VERSION + Version::ZERO,
|
||||||
|
fetched,
|
||||||
|
)?,
|
||||||
from_1sat_to_10sats: cohort::Vecs::forced_import(
|
from_1sat_to_10sats: cohort::Vecs::forced_import(
|
||||||
path,
|
path,
|
||||||
Some("from_1sat_to_10sats"),
|
Some("from_1sat_to_10sats"),
|
||||||
@@ -738,7 +748,7 @@ impl Vecs {
|
|||||||
// fetched,
|
// fetched,
|
||||||
// )?,
|
// )?,
|
||||||
// },
|
// },
|
||||||
by_spendable_type: OutputsBySpendableType {
|
by_type: OutputsBySpendableType {
|
||||||
p2pk65: cohort::Vecs::forced_import(
|
p2pk65: cohort::Vecs::forced_import(
|
||||||
path,
|
path,
|
||||||
Some("p2pk65"),
|
Some("p2pk65"),
|
||||||
@@ -819,14 +829,14 @@ impl Vecs {
|
|||||||
VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
fetched,
|
fetched,
|
||||||
)?,
|
)?,
|
||||||
// empty: cohort::Vecs::forced_import(
|
empty: cohort::Vecs::forced_import(
|
||||||
// path,
|
path,
|
||||||
// Some("empty"),
|
Some("empty"),
|
||||||
// _computation,
|
_computation,
|
||||||
// compressed,
|
compressed,
|
||||||
// VERSION + Version::ZERO,
|
VERSION + Version::ZERO,
|
||||||
// fetched,
|
fetched,
|
||||||
// )?,
|
)?,
|
||||||
unknown: cohort::Vecs::forced_import(
|
unknown: cohort::Vecs::forced_import(
|
||||||
path,
|
path,
|
||||||
Some("unknown"),
|
Some("unknown"),
|
||||||
@@ -873,18 +883,19 @@ impl Vecs {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|fetched| &fetched.chainindexes_to_close.height);
|
.map(|fetched| &fetched.chainindexes_to_close.height);
|
||||||
|
|
||||||
|
let inputindex_to_outputindex_mmap = inputindex_to_outputindex.mmap().load();
|
||||||
|
let outputindex_to_value_mmap = outputindex_to_value.mmap().load();
|
||||||
|
let outputindex_to_outputtype_mmap = outputindex_to_outputtype.mmap().load();
|
||||||
|
let outputindex_to_txindex_mmap = outputindex_to_txindex.mmap().load();
|
||||||
|
let txindex_to_height_mmap = txindex_to_height.mmap().load();
|
||||||
|
|
||||||
let mut height_to_first_outputindex_iter = height_to_first_outputindex.into_iter();
|
let mut height_to_first_outputindex_iter = height_to_first_outputindex.into_iter();
|
||||||
let mut height_to_first_inputindex_iter = height_to_first_inputindex.into_iter();
|
let mut height_to_first_inputindex_iter = height_to_first_inputindex.into_iter();
|
||||||
let mut height_to_output_count_iter = height_to_output_count.into_iter();
|
let mut height_to_output_count_iter = height_to_output_count.into_iter();
|
||||||
let mut height_to_input_count_iter = height_to_input_count.into_iter();
|
let mut height_to_input_count_iter = height_to_input_count.into_iter();
|
||||||
let mut inputindex_to_outputindex_iter = inputindex_to_outputindex.into_iter();
|
// let mut outputindex_to_value_iter_2 = outputindex_to_value.into_iter();
|
||||||
let mut outputindex_to_value_iter = outputindex_to_value.into_iter();
|
|
||||||
let mut outputindex_to_value_iter_2 = outputindex_to_value.into_iter();
|
|
||||||
let mut txindex_to_height_iter = txindex_to_height.into_iter();
|
|
||||||
let mut outputindex_to_txindex_iter = outputindex_to_txindex.into_iter();
|
|
||||||
let mut height_to_close_iter = height_to_close.as_ref().map(|v| v.into_iter());
|
let mut height_to_close_iter = height_to_close.as_ref().map(|v| v.into_iter());
|
||||||
let mut outputindex_to_outputtype_iter = outputindex_to_outputtype.into_iter();
|
// let mut outputindex_to_outputtype_iter_2 = outputindex_to_outputtype.into_iter();
|
||||||
let mut outputindex_to_outputtype_iter_2 = outputindex_to_outputtype.into_iter();
|
|
||||||
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
|
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
|
||||||
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
|
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
|
||||||
|
|
||||||
@@ -1012,104 +1023,134 @@ impl Vecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sent_handle = s.spawn(|| {
|
let sent_handle = s.spawn(|| {
|
||||||
let mut txindex_to_height = BTreeMap::new();
|
|
||||||
let mut height_to_sent: BTreeMap<
|
|
||||||
Height,
|
|
||||||
OutputsByType<(SupplyState, Vec<Sats>)>,
|
|
||||||
> = BTreeMap::new();
|
|
||||||
|
|
||||||
// Skip coinbase
|
// Skip coinbase
|
||||||
(first_inputindex + 1..first_inputindex + *input_count)
|
(first_inputindex + 1..first_inputindex + *input_count)
|
||||||
|
.into_par_iter()
|
||||||
.map(InputIndex::from)
|
.map(InputIndex::from)
|
||||||
.for_each(|inputindex| {
|
.map(|inputindex| {
|
||||||
let outputindex =
|
let outputindex = inputindex_to_outputindex
|
||||||
inputindex_to_outputindex_iter.unwrap_get_inner(inputindex);
|
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let value = outputindex_to_value_iter.unwrap_get_inner(outputindex);
|
let value = outputindex_to_value
|
||||||
|
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let input_type =
|
let input_type = outputindex_to_outputtype
|
||||||
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
|
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let input_txindex =
|
if input_type.is_unspendable() {
|
||||||
outputindex_to_txindex_iter.unwrap_get_inner(outputindex);
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
let input_height =
|
let input_txindex = outputindex_to_txindex
|
||||||
*txindex_to_height.entry(input_txindex).or_insert_with(|| {
|
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
|
||||||
txindex_to_height_iter.unwrap_get_inner(input_txindex)
|
.unwrap()
|
||||||
});
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let input_data = height_to_sent.entry(input_height).or_default();
|
// let input_height = *cached_txindex_to_height
|
||||||
|
// .entry(input_txindex)
|
||||||
|
// .or_insert_with(|| {
|
||||||
|
let height = txindex_to_height
|
||||||
|
.get_or_read(input_txindex, &txindex_to_height_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
// });
|
||||||
|
|
||||||
let (sent_supply, sats_vec) = input_data.get_mut(input_type);
|
(height, value, input_type)
|
||||||
|
})
|
||||||
sent_supply.utxos += 1;
|
.fold(
|
||||||
sent_supply.value += value;
|
BTreeMap::<Height, Transacted>::default,
|
||||||
sats_vec.push(value);
|
|mut tree, (height, value, input_type)| {
|
||||||
});
|
tree.entry(height).or_default().iterate(value, input_type);
|
||||||
|
tree
|
||||||
height_to_sent
|
},
|
||||||
|
)
|
||||||
|
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
|
||||||
|
let (mut source, to_consume) = if first.len() > second.len() {
|
||||||
|
(first, second)
|
||||||
|
} else {
|
||||||
|
(second, first)
|
||||||
|
};
|
||||||
|
to_consume.into_iter().for_each(|(k, v)| {
|
||||||
|
*source.entry(k).or_default() += v;
|
||||||
|
});
|
||||||
|
source
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let received_handle = s.spawn(|| {
|
let received_handle = s.spawn(|| {
|
||||||
let mut by_type: OutputsByType<(SupplyState, Vec<Sats>)> =
|
|
||||||
OutputsByType::default();
|
|
||||||
|
|
||||||
(first_outputindex..first_outputindex + *output_count)
|
(first_outputindex..first_outputindex + *output_count)
|
||||||
|
.into_par_iter()
|
||||||
.map(OutputIndex::from)
|
.map(OutputIndex::from)
|
||||||
.for_each(|outputindex| {
|
.map(|outputindex| {
|
||||||
let value =
|
let value = outputindex_to_value
|
||||||
outputindex_to_value_iter_2.unwrap_get_inner(outputindex);
|
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let output_type =
|
let output_type = outputindex_to_outputtype
|
||||||
outputindex_to_outputtype_iter_2.unwrap_get_inner(outputindex);
|
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let (received_supply, sats_vec) = by_type.get_mut(output_type);
|
(value, output_type)
|
||||||
|
})
|
||||||
received_supply.value += value;
|
.fold(
|
||||||
received_supply.utxos += 1;
|
Transacted::default,
|
||||||
sats_vec.push(value);
|
|mut transacted, (value, output_type)| {
|
||||||
});
|
transacted.iterate(value, output_type);
|
||||||
|
transacted
|
||||||
by_type
|
},
|
||||||
|
)
|
||||||
|
.reduce(Transacted::default, |acc, transacted| acc + transacted)
|
||||||
});
|
});
|
||||||
|
|
||||||
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
||||||
});
|
});
|
||||||
|
|
||||||
unspendable_supply += received
|
unspendable_supply += received
|
||||||
|
.by_type
|
||||||
.unspendable
|
.unspendable
|
||||||
.as_vec()
|
.as_vec()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|state| state.0.value)
|
.map(|state| state.value)
|
||||||
.sum::<Sats>()
|
.sum::<Sats>()
|
||||||
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
||||||
|
|
||||||
if height == Height::new(0) {
|
if height == Height::new(0) {
|
||||||
received.spendable.p2pk65.1.remove(0);
|
received = Transacted::default();
|
||||||
received.spendable.p2pk65.0.utxos -= 1;
|
|
||||||
received.spendable.p2pk65.0.value -= Sats::FIFTY_BTC;
|
|
||||||
unspendable_supply += Sats::FIFTY_BTC;
|
unspendable_supply += Sats::FIFTY_BTC;
|
||||||
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
||||||
// Need to destroy invalid coinbases due to duplicate txids
|
// Need to destroy invalid coinbases due to duplicate txids
|
||||||
let entry = if height == Height::new(91_842) {
|
if height == Height::new(91_842) {
|
||||||
height_to_sent.entry(Height::new(91_812)).or_default()
|
height_to_sent.entry(Height::new(91_812)).or_default()
|
||||||
} else {
|
} else {
|
||||||
height_to_sent.entry(Height::new(91_722)).or_default()
|
height_to_sent.entry(Height::new(91_722)).or_default()
|
||||||
};
|
}
|
||||||
entry.spendable.p2pk65.0.value += Sats::FIFTY_BTC;
|
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
|
||||||
entry.spendable.p2pk65.0.utxos += 1;
|
|
||||||
entry.spendable.p2pk65.1.push(Sats::FIFTY_BTC);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if chain_state_starting_height <= height {
|
if chain_state_starting_height <= height {
|
||||||
// RECEIVE
|
// RECEIVE
|
||||||
|
|
||||||
// Push current block state before processing sends and receives
|
// Push current block state before processing sends and receives
|
||||||
chain_state.push(BlockState::from(ReceivedBlockStateData {
|
chain_state.push(BlockState {
|
||||||
received: &received,
|
supply: received.spendable_supply.clone(),
|
||||||
price,
|
price,
|
||||||
timestamp,
|
timestamp,
|
||||||
}));
|
});
|
||||||
|
|
||||||
self.utxos_vecs.receive(received, height, price);
|
self.utxos_vecs.receive(received, height, price);
|
||||||
|
|
||||||
@@ -1117,17 +1158,12 @@ impl Vecs {
|
|||||||
|
|
||||||
// SEND
|
// SEND
|
||||||
|
|
||||||
height_to_sent
|
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
|
||||||
.iter()
|
|
||||||
.for_each(|(height, sent_data_by_type)| {
|
|
||||||
let block_state =
|
|
||||||
chain_state.get_mut(height.unwrap_to_usize()).unwrap();
|
|
||||||
|
|
||||||
sent_data_by_type
|
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
|
||||||
.as_vec()
|
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
|
||||||
.into_iter()
|
&sent.spendable_supply;
|
||||||
.for_each(|(supply, _)| block_state.supply -= supply);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
||||||
} else {
|
} else {
|
||||||
@@ -1151,6 +1187,8 @@ impl Vecs {
|
|||||||
|
|
||||||
exit.block();
|
exit.block();
|
||||||
|
|
||||||
|
info!("Computing utxo set datasets...");
|
||||||
|
|
||||||
let mut flat_vecs_ = self.utxos_vecs.as_mut_vec();
|
let mut flat_vecs_ = self.utxos_vecs.as_mut_vec();
|
||||||
|
|
||||||
// Flush rest of values
|
// Flush rest of values
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ pub struct Dollars(f64);
|
|||||||
|
|
||||||
impl Dollars {
|
impl Dollars {
|
||||||
pub const ZERO: Self = Self(0.0);
|
pub const ZERO: Self = Self(0.0);
|
||||||
|
pub const NAN: Self = Self(f64::NAN);
|
||||||
|
|
||||||
pub const fn mint(dollars: f64) -> Self {
|
pub const fn mint(dollars: f64) -> Self {
|
||||||
Self(dollars)
|
Self(dollars)
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ impl OutputType {
|
|||||||
Self::P2WSH => true,
|
Self::P2WSH => true,
|
||||||
Self::P2TR => true,
|
Self::P2TR => true,
|
||||||
Self::P2A => true,
|
Self::P2A => true,
|
||||||
Self::Empty => false,
|
Self::Empty => true,
|
||||||
Self::Unknown => false,
|
Self::Unknown => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ impl Sats {
|
|||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
*self == Self::ZERO
|
*self == Self::ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_not_zero(&self) -> bool {
|
||||||
|
*self != Self::ZERO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Sats {
|
impl Add for Sats {
|
||||||
@@ -140,6 +144,12 @@ impl From<Sats> for f64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Sats> for usize {
|
||||||
|
fn from(value: Sats) -> Self {
|
||||||
|
value.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Amount> for Sats {
|
impl From<Amount> for Sats {
|
||||||
fn from(value: Amount) -> Self {
|
fn from(value: Amount) -> Self {
|
||||||
Self(value.to_sat())
|
Self(value.to_sat())
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ impl Fetcher {
|
|||||||
pub fn get_date(&mut self, date: Date) -> color_eyre::Result<OHLCCents> {
|
pub fn get_date(&mut self, date: Date) -> color_eyre::Result<OHLCCents> {
|
||||||
self.kraken
|
self.kraken
|
||||||
.get_from_1d(&date)
|
.get_from_1d(&date)
|
||||||
.or_else(|e| {
|
.or_else(|_| {
|
||||||
// eprintln!("{e}");
|
// eprintln!("{e}");
|
||||||
self.binance.get_from_1d(&date)
|
self.binance.get_from_1d(&date)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ impl<'a> VecTrees<'a> {
|
|||||||
.id_to_index_to_vec
|
.id_to_index_to_vec
|
||||||
.entry(key.clone())
|
.entry(key.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(index.clone(), vec);
|
.insert(index, vec);
|
||||||
if prev.is_some() {
|
if prev.is_some() {
|
||||||
dbg!(&key, str, name);
|
dbg!(&key, str, name);
|
||||||
panic!()
|
panic!()
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ impl<'a, T> UnsafeSlice<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SAFETY: It is UB
|
||||||
|
pub fn get(&self, i: usize) -> *mut T {
|
||||||
|
self.0[i].get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn copy_slice(&self, start: usize, slice: &[T])
|
pub fn copy_slice(&self, start: usize, slice: &[T])
|
||||||
where
|
where
|
||||||
T: Copy,
|
T: Copy,
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use arc_swap::ArcSwap;
|
||||||
use brk_core::{
|
use brk_core::{
|
||||||
Bitcoin, CheckedSub, Close, Date, DateIndex, Dollars, Height, Sats, StoredUsize, TxIndex,
|
Bitcoin, CheckedSub, Close, Date, DateIndex, Dollars, Height, Sats, StoredUsize, TxIndex,
|
||||||
};
|
};
|
||||||
use brk_exit::Exit;
|
use brk_exit::Exit;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use memmap2::Mmap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyCollectableVec, AnyIterableVec, AnyVec, BoxedVecIterator, CollectableVec, Compressed, Error,
|
AnyCollectableVec, AnyIterableVec, AnyVec, BoxedVecIterator, CollectableVec, Compressed, Error,
|
||||||
@@ -97,6 +99,14 @@ where
|
|||||||
self.inner.path()
|
self.inner.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_or_read(&self, index: I, mmap: &Mmap) -> Result<Option<Value<T>>> {
|
||||||
|
self.inner.get_or_read(index, mmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||||
|
self.inner.mmap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn inner_version(&self) -> Version {
|
pub fn inner_version(&self) -> Version {
|
||||||
self.inner.version()
|
self.inner.version()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -352,18 +352,19 @@ function createPartialOptions(colors) {
|
|||||||
*
|
*
|
||||||
* @param {Object} args
|
* @param {Object} args
|
||||||
* @param {string} args.name
|
* @param {string} args.name
|
||||||
|
* @param {string} args.legend
|
||||||
* @param {string} args.title
|
* @param {string} args.title
|
||||||
* @param {VecIdRatioCapBase} args.key
|
* @param {VecIdRatioCapBase} args.key
|
||||||
* @param {Color} [args.color]
|
* @param {Color} [args.color]
|
||||||
*/
|
*/
|
||||||
function createPriceWithRatio({ name, title, key, color }) {
|
function createPriceWithRatio({ name, title, legend, key, color }) {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
title,
|
title,
|
||||||
top: [
|
top: [
|
||||||
createBaseSeries({
|
createBaseSeries({
|
||||||
key,
|
key,
|
||||||
name: "Average",
|
name: legend,
|
||||||
color,
|
color,
|
||||||
}),
|
}),
|
||||||
createBaseSeries({
|
createBaseSeries({
|
||||||
@@ -633,6 +634,7 @@ function createPartialOptions(colors) {
|
|||||||
createPriceWithRatio({
|
createPriceWithRatio({
|
||||||
key: `${key}realized-price`,
|
key: `${key}realized-price`,
|
||||||
name: "realized price",
|
name: "realized price",
|
||||||
|
legend: "realized",
|
||||||
title: `${title} Realized Price`,
|
title: `${title} Realized Price`,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@@ -747,6 +749,7 @@ function createPartialOptions(colors) {
|
|||||||
key: `${key}-sma`,
|
key: `${key}-sma`,
|
||||||
name,
|
name,
|
||||||
title: `${name} Market Price Moving Average`,
|
title: `${name} Market Price Moving Average`,
|
||||||
|
legend: "average",
|
||||||
color: colors[`_${key}`],
|
color: colors[`_${key}`],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@@ -785,6 +788,11 @@ function createPartialOptions(colors) {
|
|||||||
],
|
],
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Investing",
|
||||||
|
tree: [
|
||||||
{
|
{
|
||||||
name: "DCA vs Lump sum",
|
name: "DCA vs Lump sum",
|
||||||
tree: [
|
tree: [
|
||||||
@@ -1581,6 +1589,71 @@ function createPartialOptions(colors) {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Range",
|
||||||
|
tree: [
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-1d-to-1w",
|
||||||
|
name: "1d..1w",
|
||||||
|
title: "Between 1 Day and 1 Week",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-1w-to-1m",
|
||||||
|
name: "1w..1m",
|
||||||
|
title: "Between 1 Week and 1 Month",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-1m-to-3m",
|
||||||
|
name: "1m..3m",
|
||||||
|
title: "Between 1 Month and 3 Months",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-3m-to-6m",
|
||||||
|
name: "3m..6m",
|
||||||
|
title: "Between 3 Month and 6 Months",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-6m-to-1y",
|
||||||
|
name: "6m..1y",
|
||||||
|
title: "Between 6 Months and 1 Year",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-1y-to-2y",
|
||||||
|
name: "1y..2y",
|
||||||
|
title: "Between 1 Year and 2 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-2y-to-3y",
|
||||||
|
name: "2y..3y",
|
||||||
|
title: "Between 2 Years and 3 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-3y-to-4y",
|
||||||
|
name: "3y..4y",
|
||||||
|
title: "Between 3 Years and 4 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-4y-to-5y",
|
||||||
|
name: "4y..5y",
|
||||||
|
title: "Between 4 Years and 5 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-5y-to-7y",
|
||||||
|
name: "5y..7y",
|
||||||
|
title: "Between 5 Years and 7 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-7y-to-10y",
|
||||||
|
name: "7y..10y",
|
||||||
|
title: "Between 7 Years and 10 Years",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-10y-to-15y",
|
||||||
|
name: "10y..15y",
|
||||||
|
title: "Between 10 Years and 15 Years",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Epoch",
|
name: "Epoch",
|
||||||
tree: [
|
tree: [
|
||||||
@@ -1615,74 +1688,79 @@ function createPartialOptions(colors) {
|
|||||||
name: "size",
|
name: "size",
|
||||||
tree: [
|
tree: [
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-1sat-10sats",
|
key: "0sat",
|
||||||
|
name: "0sat",
|
||||||
|
title: "0 sat",
|
||||||
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "from-1sat-to-10sats",
|
||||||
name: "1sat..10sats",
|
name: "1sat..10sats",
|
||||||
title: "UTXOs from 1 sat to 10 sats",
|
title: "From 1 sat to 10 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-10sats-100sats",
|
key: "from-10sats-to-100sats",
|
||||||
name: "10sat..100sats",
|
name: "10sat..100sats",
|
||||||
title: "UTXOs from 10 sats to 100 sats",
|
title: "From 10 sats to 100 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-100sats-1-000sats",
|
key: "from-100sats-to-1-000sats",
|
||||||
name: "100sat..1_000sats",
|
name: "100sat..1_000sats",
|
||||||
title: "UTXOs from 100 sats to 1,000 sats",
|
title: "From 100 sats to 1,000 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-1-000sats-10-000sats",
|
key: "from-1-000sats-to-10-000sats",
|
||||||
name: "1_000sat..10_000sats",
|
name: "1_000sat..10_000sats",
|
||||||
title: "UTXOs from 1,000 sats to 10,000 sats",
|
title: "From 1,000 sats to 10,000 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-10-000sats-100-000sats",
|
key: "from-10-000sats-to-100-000sats",
|
||||||
name: "10_000sat..100_000sats",
|
name: "10_000sat..100_000sats",
|
||||||
title: "UTXOs from 10,000 sats to 100,000 sats",
|
title: "From 10,000 sats to 100,000 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-100-000sats-1-000-000sats",
|
key: "from-100-000sats-to-1-000-000sats",
|
||||||
name: "100_000sat..1_000_000sats",
|
name: "100_000sat..1_000_000sats",
|
||||||
title: "UTXOs from 100,000 sats to 1,000,000 sats",
|
title: "From 100,000 sats to 1,000,000 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-1-000-000sats-10-000-000sats",
|
key: "from-1-000-000sats-to-10-000-000sats",
|
||||||
name: "1_000_000sat..10_000_000sats",
|
name: "1_000_000sat..10_000_000sats",
|
||||||
title: "UTXOs from 1,000,000 sats to 10,000,000 sats",
|
title: "From 1,000,000 sats to 10,000,000 sats",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-10-000-000sats-1btc",
|
key: "from-10-000-000sats-to-1btc",
|
||||||
name: "10_000_000sat..1btc",
|
name: "10_000_000sat..1btc",
|
||||||
title: "UTXOs from 10,000,000 sats to 1 BTC",
|
title: "From 10,000,000 sats to 1 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-1btc-10btc",
|
key: "from-1btc-to-10btc",
|
||||||
name: "1btc..10btc",
|
name: "1btc..10btc",
|
||||||
title: "UTXOs from 1 BTC to 10 BTC",
|
title: "From 1 BTC to 10 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-10btc-100btc",
|
key: "from-10btc-to-100btc",
|
||||||
name: "10btc..100btc",
|
name: "10btc..100btc",
|
||||||
title: "UTXOs from 10 BTC to 100 BTC",
|
title: "From 10 BTC to 100 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-100btc-1-000btc",
|
key: "from-100btc-to-1-000btc",
|
||||||
name: "100btc..1_000btc",
|
name: "100btc..1_000btc",
|
||||||
title: "UTXOs from 100 BTC to 1,000 BTC",
|
title: "From 100 BTC to 1,000 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-1-000btc-10-000btc",
|
key: "from-1-000btc-to-10-000btc",
|
||||||
name: "1_000btc..10_000btc",
|
name: "1_000btc..10_000btc",
|
||||||
title: "UTXOs from 1,000 BTC to 10,000 BTC",
|
title: "From 1,000 BTC to 10,000 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-10-000btc-100-000btc",
|
key: "from-10-000btc-to-100-000btc",
|
||||||
name: "10_000btc..100_000btc",
|
name: "10_000btc..100_000btc",
|
||||||
title: "UTXOs from 10,000 BTC to 100,000 BTC",
|
title: "From 10,000 BTC to 100,000 BTC",
|
||||||
}),
|
}),
|
||||||
createUTXOGroupFolder({
|
createUTXOGroupFolder({
|
||||||
key: "from-100-000btc",
|
key: "from-100-000btc",
|
||||||
name: "100_000btc..inf",
|
name: "100_000btc+",
|
||||||
title: "UTXOs from 100,000 BTC",
|
title: "From 100,000 BTC",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -1739,6 +1817,11 @@ function createPartialOptions(colors) {
|
|||||||
name: "unknown",
|
name: "unknown",
|
||||||
title: "Pay To Unknown",
|
title: "Pay To Unknown",
|
||||||
}),
|
}),
|
||||||
|
createUTXOGroupFolder({
|
||||||
|
key: "empty",
|
||||||
|
name: "empty",
|
||||||
|
title: "Pay To Empty",
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user