mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-24 01:18:10 -07:00
global: opreturn part 5
This commit is contained in:
@@ -3,7 +3,7 @@ use brk_indexer::Indexer;
|
||||
use brk_types::{BasisPoints16, Height, OpReturnKind, StoredU64, VSize};
|
||||
use vecdb::{AnyVec, Exit, ReadableVec, VecIndex};
|
||||
|
||||
use super::{Vecs, vecs::Totals};
|
||||
use super::{Breakdown, Vecs, vecs::Totals};
|
||||
use crate::{
|
||||
blocks,
|
||||
internal::{PercentPerBlock, RatioU64Bp16},
|
||||
@@ -15,30 +15,30 @@ const WRITE_INTERVAL: usize = 10_000;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct PolicyTotals {
|
||||
standard: Totals,
|
||||
pre_v30_standard: Totals,
|
||||
pre_v30_nonstandard: Totals,
|
||||
oversized: Totals,
|
||||
multiple: Totals,
|
||||
pre_v30_nonstandard: Totals,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct Carrier {
|
||||
kinds: u32,
|
||||
output_count: u64,
|
||||
post_op_return_bytes: u64,
|
||||
data_bytes: u64,
|
||||
oversized_output_count: u64,
|
||||
oversized_post_op_return_bytes: u64,
|
||||
oversized_data_bytes: u64,
|
||||
vsize: VSize,
|
||||
}
|
||||
|
||||
impl Carrier {
|
||||
fn add_output(&mut self, kind: OpReturnKind, post_op_return_bytes: u64) {
|
||||
fn add_output(&mut self, kind: OpReturnKind, data_bytes: u64) {
|
||||
self.kinds |= kind_bit(kind);
|
||||
self.output_count += 1;
|
||||
self.post_op_return_bytes += post_op_return_bytes;
|
||||
if post_op_return_bytes > OLD_STANDARD_MAX_POST_OP_RETURN_BYTES {
|
||||
self.data_bytes += data_bytes;
|
||||
if data_bytes > OLD_STANDARD_MAX_POST_OP_RETURN_BYTES {
|
||||
self.oversized_output_count += 1;
|
||||
self.oversized_post_op_return_bytes += post_op_return_bytes;
|
||||
self.oversized_data_bytes += data_bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,9 +110,9 @@ impl Vecs {
|
||||
carrier.vsize = VSize::from(weight_cursor.next().unwrap());
|
||||
}
|
||||
|
||||
total.post_op_return_bytes += bytes;
|
||||
total.data_bytes += bytes;
|
||||
by_kind[kind_index].output_count += 1;
|
||||
by_kind[kind_index].post_op_return_bytes += bytes;
|
||||
by_kind[kind_index].data_bytes += bytes;
|
||||
carrier.add_output(kind, bytes);
|
||||
}
|
||||
|
||||
@@ -122,12 +122,12 @@ impl Vecs {
|
||||
for (kind, metrics) in self.by_kind.iter_typed_mut() {
|
||||
metrics.push(by_kind[kind as usize]);
|
||||
}
|
||||
self.policy.standard.push(policy.standard);
|
||||
self.policy.oversized.push(policy.oversized);
|
||||
self.policy.multiple.push(policy.multiple);
|
||||
self.policy.pre_v30_standard.push(policy.pre_v30_standard);
|
||||
self.policy
|
||||
.pre_v30_nonstandard
|
||||
.push(policy.pre_v30_nonstandard);
|
||||
self.policy.oversized.push(policy.oversized);
|
||||
self.policy.multiple.push(policy.multiple);
|
||||
|
||||
if (height + 1).is_multiple_of(WRITE_INTERVAL) {
|
||||
let _lock = exit.lock();
|
||||
@@ -144,16 +144,26 @@ impl Vecs {
|
||||
let block_size = &blocks.size.size.cumulative.height;
|
||||
compute_data_share(
|
||||
starting_lengths.height,
|
||||
&mut self.total.data_share,
|
||||
&self.total.metrics.post_op_return_bytes.cumulative.height,
|
||||
&mut self.total.chain_share,
|
||||
&self.total.metrics.data_bytes.cumulative.height,
|
||||
block_size,
|
||||
exit,
|
||||
)?;
|
||||
for policy in self.policy.iter_mut() {
|
||||
compute_data_share(
|
||||
let total_data = &self.total.metrics.data_bytes.cumulative.height;
|
||||
for breakdown in self.by_kind.iter_mut() {
|
||||
compute_breakdown_data_shares(
|
||||
starting_lengths.height,
|
||||
&mut policy.data_share,
|
||||
&policy.metrics.total.post_op_return_bytes.cumulative.height,
|
||||
breakdown,
|
||||
total_data,
|
||||
block_size,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
for policy in self.policy.iter_mut() {
|
||||
compute_breakdown_data_shares(
|
||||
starting_lengths.height,
|
||||
policy,
|
||||
total_data,
|
||||
block_size,
|
||||
exit,
|
||||
)?;
|
||||
@@ -168,6 +178,18 @@ impl Vecs {
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_breakdown_data_shares(
|
||||
max_from: Height,
|
||||
breakdown: &mut Breakdown,
|
||||
total_data: &impl ReadableVec<Height, StoredU64>,
|
||||
block_size: &impl ReadableVec<Height, StoredU64>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let data = &breakdown.metrics.total.data_bytes.cumulative.height;
|
||||
compute_data_share(max_from, &mut breakdown.chain_share, data, block_size, exit)?;
|
||||
compute_data_share(max_from, &mut breakdown.data_share, data, total_data, exit)
|
||||
}
|
||||
|
||||
fn compute_data_share(
|
||||
max_from: Height,
|
||||
target: &mut PercentPerBlock<BasisPoints16>,
|
||||
@@ -198,30 +220,30 @@ fn finalize_transaction(
|
||||
|
||||
if carrier.oversized_output_count > 0 {
|
||||
policy.oversized.output_count += carrier.oversized_output_count;
|
||||
policy.oversized.post_op_return_bytes += carrier.oversized_post_op_return_bytes;
|
||||
policy.oversized.data_bytes += carrier.oversized_data_bytes;
|
||||
add_carrier(&mut policy.oversized, carrier.vsize);
|
||||
}
|
||||
|
||||
if carrier.output_count > 1 {
|
||||
policy.multiple.output_count += carrier.output_count;
|
||||
policy.multiple.post_op_return_bytes += carrier.post_op_return_bytes;
|
||||
policy.multiple.data_bytes += carrier.data_bytes;
|
||||
add_carrier(&mut policy.multiple, carrier.vsize);
|
||||
}
|
||||
|
||||
if carrier.oversized_output_count > 0 || carrier.output_count > 1 {
|
||||
policy.pre_v30_nonstandard.output_count += carrier.output_count;
|
||||
policy.pre_v30_nonstandard.post_op_return_bytes += carrier.post_op_return_bytes;
|
||||
policy.pre_v30_nonstandard.data_bytes += carrier.data_bytes;
|
||||
add_carrier(&mut policy.pre_v30_nonstandard, carrier.vsize);
|
||||
} else {
|
||||
policy.standard.output_count += carrier.output_count;
|
||||
policy.standard.post_op_return_bytes += carrier.post_op_return_bytes;
|
||||
add_carrier(&mut policy.standard, carrier.vsize);
|
||||
policy.pre_v30_standard.output_count += carrier.output_count;
|
||||
policy.pre_v30_standard.data_bytes += carrier.data_bytes;
|
||||
add_carrier(&mut policy.pre_v30_standard, carrier.vsize);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_carrier(metrics: &mut Totals, vsize: VSize) {
|
||||
metrics.carrier_tx_count += 1;
|
||||
metrics.carrier_vsize += vsize;
|
||||
metrics.tx_count += 1;
|
||||
metrics.tx_vsize += vsize;
|
||||
}
|
||||
|
||||
const fn kind_bit(kind: OpReturnKind) -> u32 {
|
||||
@@ -246,13 +268,13 @@ mod tests {
|
||||
|
||||
finalize_transaction(&mut total, &mut by_kind, &mut policy, carrier);
|
||||
|
||||
assert_eq!(total.carrier_tx_count, 1);
|
||||
assert_eq!(by_kind[OpReturnKind::Runes as usize].carrier_tx_count, 1);
|
||||
assert_eq!(by_kind[OpReturnKind::Omni as usize].carrier_tx_count, 1);
|
||||
assert_eq!(total.tx_count, 1);
|
||||
assert_eq!(by_kind[OpReturnKind::Runes as usize].tx_count, 1);
|
||||
assert_eq!(by_kind[OpReturnKind::Omni as usize].tx_count, 1);
|
||||
assert_eq!(policy.multiple.output_count, 2);
|
||||
assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 1);
|
||||
assert_eq!(policy.oversized.carrier_tx_count, 0);
|
||||
assert_eq!(policy.standard.carrier_tx_count, 0);
|
||||
assert_eq!(policy.pre_v30_nonstandard.tx_count, 1);
|
||||
assert_eq!(policy.oversized.tx_count, 0);
|
||||
assert_eq!(policy.pre_v30_standard.tx_count, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -269,10 +291,10 @@ mod tests {
|
||||
finalize_transaction(&mut total, &mut by_kind, &mut policy, carrier);
|
||||
|
||||
assert_eq!(policy.oversized.output_count, 1);
|
||||
assert_eq!(policy.oversized.carrier_vsize, VSize::new(120));
|
||||
assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 1);
|
||||
assert_eq!(policy.multiple.carrier_tx_count, 0);
|
||||
assert_eq!(policy.standard.carrier_tx_count, 0);
|
||||
assert_eq!(policy.oversized.tx_vsize, VSize::new(120));
|
||||
assert_eq!(policy.pre_v30_nonstandard.tx_count, 1);
|
||||
assert_eq!(policy.multiple.tx_count, 0);
|
||||
assert_eq!(policy.pre_v30_standard.tx_count, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -288,10 +310,10 @@ mod tests {
|
||||
|
||||
finalize_transaction(&mut total, &mut by_kind, &mut policy, carrier);
|
||||
|
||||
assert_eq!(policy.standard.output_count, 1);
|
||||
assert_eq!(policy.standard.post_op_return_bytes, 15);
|
||||
assert_eq!(policy.standard.carrier_tx_count, 1);
|
||||
assert_eq!(policy.standard.carrier_vsize, VSize::new(100));
|
||||
assert_eq!(policy.pre_v30_nonstandard.carrier_tx_count, 0);
|
||||
assert_eq!(policy.pre_v30_standard.output_count, 1);
|
||||
assert_eq!(policy.pre_v30_standard.data_bytes, 15);
|
||||
assert_eq!(policy.pre_v30_standard.tx_count, 1);
|
||||
assert_eq!(policy.pre_v30_standard.tx_vsize, VSize::new(100));
|
||||
assert_eq!(policy.pre_v30_nonstandard.tx_count, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::path::Path;
|
||||
use brk_error::Result;
|
||||
use brk_types::Version;
|
||||
|
||||
use super::{ByKind, Metrics, Policy, Total, Vecs};
|
||||
use super::{Breakdown, ByKind, Policy, Total, Vecs};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
@@ -22,7 +22,7 @@ impl Vecs {
|
||||
let db = open_db(parent_path, super::DB_NAME, 1_000_000)?;
|
||||
let total = Total::forced_import(&db, "op_return", version, indexes, cached_starts)?;
|
||||
let by_kind = ByKind::try_new(|_, name| {
|
||||
Metrics::forced_import(
|
||||
Breakdown::forced_import(
|
||||
&db,
|
||||
&format!("op_return_{name}"),
|
||||
version,
|
||||
|
||||
@@ -4,6 +4,6 @@ mod import;
|
||||
mod vecs;
|
||||
|
||||
pub use by_kind::ByKind;
|
||||
pub use vecs::{Metrics, Policy, Total, Vecs};
|
||||
pub use vecs::{Breakdown, Policy, Total, Vecs};
|
||||
|
||||
pub const DB_NAME: &str = "op_return";
|
||||
|
||||
@@ -15,16 +15,16 @@ pub type Series<T, M = Rw> = PerBlockCumulativeRolling<T, T, M>;
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub(super) struct Totals {
|
||||
pub output_count: u64,
|
||||
pub post_op_return_bytes: u64,
|
||||
pub carrier_tx_count: u64,
|
||||
pub carrier_vsize: VSize,
|
||||
pub data_bytes: u64,
|
||||
pub tx_count: u64,
|
||||
pub tx_vsize: VSize,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct TotalMetrics<M: StorageMode = Rw> {
|
||||
pub post_op_return_bytes: Series<StoredU64, M>,
|
||||
pub carrier_tx_count: Series<StoredU64, M>,
|
||||
pub carrier_vsize: Series<VSize, M>,
|
||||
pub data_bytes: Series<StoredU64, M>,
|
||||
pub tx_count: Series<StoredU64, M>,
|
||||
pub tx_vsize: Series<VSize, M>,
|
||||
}
|
||||
|
||||
impl TotalMetrics {
|
||||
@@ -36,23 +36,23 @@ impl TotalMetrics {
|
||||
cached_starts: &Windows<&WindowStartVec>,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
post_op_return_bytes: Series::forced_import(
|
||||
data_bytes: Series::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_post_op_return_bytes"),
|
||||
&format!("{prefix}_data_bytes"),
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
carrier_tx_count: Series::forced_import(
|
||||
tx_count: Series::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_carrier_tx_count"),
|
||||
&format!("{prefix}_tx_count"),
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
carrier_vsize: Series::forced_import(
|
||||
tx_vsize: Series::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_carrier_vsize"),
|
||||
&format!("{prefix}_tx_vsize"),
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
@@ -61,54 +61,46 @@ impl TotalMetrics {
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.post_op_return_bytes
|
||||
self.data_bytes
|
||||
.block
|
||||
.len()
|
||||
.min(self.carrier_tx_count.block.len())
|
||||
.min(self.carrier_vsize.block.len())
|
||||
.min(self.tx_count.block.len())
|
||||
.min(self.tx_vsize.block.len())
|
||||
}
|
||||
|
||||
pub(super) fn push(&mut self, block: Totals) {
|
||||
self.post_op_return_bytes
|
||||
.block
|
||||
.push(block.post_op_return_bytes.into());
|
||||
self.carrier_tx_count
|
||||
.block
|
||||
.push(block.carrier_tx_count.into());
|
||||
self.carrier_vsize.block.push(block.carrier_vsize);
|
||||
self.data_bytes.block.push(block.data_bytes.into());
|
||||
self.tx_count.block.push(block.tx_count.into());
|
||||
self.tx_vsize.block.push(block.tx_vsize);
|
||||
}
|
||||
|
||||
fn validate_and_truncate(&mut self, version: Version, height: Height) -> Result<()> {
|
||||
self.post_op_return_bytes
|
||||
.block
|
||||
.validate_and_truncate(version, height)?;
|
||||
self.carrier_tx_count
|
||||
.block
|
||||
.validate_and_truncate(version, height)?;
|
||||
self.carrier_vsize
|
||||
self.data_bytes
|
||||
.block
|
||||
.validate_and_truncate(version, height)?;
|
||||
self.tx_count.block.validate_and_truncate(version, height)?;
|
||||
self.tx_vsize.block.validate_and_truncate(version, height)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn truncate_if_needed_at(&mut self, len: usize) -> Result<()> {
|
||||
self.post_op_return_bytes.block.truncate_if_needed_at(len)?;
|
||||
self.carrier_tx_count.block.truncate_if_needed_at(len)?;
|
||||
self.carrier_vsize.block.truncate_if_needed_at(len)?;
|
||||
self.data_bytes.block.truncate_if_needed_at(len)?;
|
||||
self.tx_count.block.truncate_if_needed_at(len)?;
|
||||
self.tx_vsize.block.truncate_if_needed_at(len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self) -> Result<()> {
|
||||
self.post_op_return_bytes.block.write()?;
|
||||
self.carrier_tx_count.block.write()?;
|
||||
self.carrier_vsize.block.write()?;
|
||||
self.data_bytes.block.write()?;
|
||||
self.tx_count.block.write()?;
|
||||
self.tx_vsize.block.write()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_cumulative(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
self.post_op_return_bytes.compute_rest(max_from, exit)?;
|
||||
self.carrier_tx_count.compute_rest(max_from, exit)?;
|
||||
self.carrier_vsize.compute_rest(max_from, exit)?;
|
||||
self.data_bytes.compute_rest(max_from, exit)?;
|
||||
self.tx_count.compute_rest(max_from, exit)?;
|
||||
self.tx_vsize.compute_rest(max_from, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -119,7 +111,7 @@ pub struct Total<M: StorageMode = Rw> {
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub metrics: TotalMetrics<M>,
|
||||
pub data_share: PercentPerBlock<BasisPoints16, M>,
|
||||
pub chain_share: PercentPerBlock<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
impl Total {
|
||||
@@ -132,9 +124,9 @@ impl Total {
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
metrics: TotalMetrics::forced_import(db, prefix, version, indexes, cached_starts)?,
|
||||
data_share: PercentPerBlock::forced_import(
|
||||
chain_share: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_data_share"),
|
||||
&format!("{prefix}_chain_share"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
@@ -206,16 +198,17 @@ impl Metrics {
|
||||
}
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct PolicyMetrics<M: StorageMode = Rw> {
|
||||
pub struct Breakdown<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub metrics: Metrics<M>,
|
||||
pub data_share: PercentPerBlock<BasisPoints16, M>,
|
||||
pub chain_share: PercentPerBlock<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
impl PolicyMetrics {
|
||||
fn forced_import(
|
||||
impl Breakdown {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
prefix: &str,
|
||||
version: Version,
|
||||
@@ -230,16 +223,22 @@ impl PolicyMetrics {
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
chain_share: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_chain_share"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Policy<M: StorageMode = Rw> {
|
||||
pub standard: PolicyMetrics<M>,
|
||||
pub oversized: PolicyMetrics<M>,
|
||||
pub multiple: PolicyMetrics<M>,
|
||||
pub pre_v30_nonstandard: PolicyMetrics<M>,
|
||||
pub pre_v30_standard: Breakdown<M>,
|
||||
pub pre_v30_nonstandard: Breakdown<M>,
|
||||
pub oversized: Breakdown<M>,
|
||||
pub multiple: Breakdown<M>,
|
||||
}
|
||||
|
||||
impl Policy {
|
||||
@@ -250,7 +249,7 @@ impl Policy {
|
||||
cached_starts: &Windows<&WindowStartVec>,
|
||||
) -> Result<Self> {
|
||||
let import = |name| {
|
||||
PolicyMetrics::forced_import(
|
||||
Breakdown::forced_import(
|
||||
db,
|
||||
&format!("op_return_policy_{name}"),
|
||||
version,
|
||||
@@ -260,29 +259,29 @@ impl Policy {
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
standard: import("standard")?,
|
||||
pre_v30_standard: import("pre_v30_standard")?,
|
||||
pre_v30_nonstandard: import("pre_v30_nonstandard")?,
|
||||
oversized: import("oversized")?,
|
||||
multiple: import("multiple")?,
|
||||
pre_v30_nonstandard: import("pre_v30_nonstandard")?,
|
||||
})
|
||||
}
|
||||
|
||||
fn iter(&self) -> impl Iterator<Item = &PolicyMetrics> {
|
||||
fn iter(&self) -> impl Iterator<Item = &Breakdown> {
|
||||
[
|
||||
&self.standard,
|
||||
&self.pre_v30_standard,
|
||||
&self.pre_v30_nonstandard,
|
||||
&self.oversized,
|
||||
&self.multiple,
|
||||
&self.pre_v30_nonstandard,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub(super) fn iter_mut(&mut self) -> impl Iterator<Item = &mut PolicyMetrics> {
|
||||
pub(super) fn iter_mut(&mut self) -> impl Iterator<Item = &mut Breakdown> {
|
||||
[
|
||||
&mut self.standard,
|
||||
&mut self.pre_v30_standard,
|
||||
&mut self.pre_v30_nonstandard,
|
||||
&mut self.oversized,
|
||||
&mut self.multiple,
|
||||
&mut self.pre_v30_nonstandard,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -293,7 +292,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
pub(crate) db: Database,
|
||||
pub total: Total<M>,
|
||||
pub by_kind: ByKind<Metrics<M>>,
|
||||
pub by_kind: ByKind<Breakdown<M>>,
|
||||
pub policy: Policy<M>,
|
||||
}
|
||||
|
||||
@@ -302,7 +301,7 @@ impl Vecs {
|
||||
let len = self
|
||||
.by_kind
|
||||
.iter()
|
||||
.map(Metrics::len)
|
||||
.map(|metrics| metrics.len())
|
||||
.fold(self.total.len(), usize::min);
|
||||
self.policy
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user