global: opreturn part 5

This commit is contained in:
nym21
2026-07-19 18:19:48 +02:00
parent 0fc61d7932
commit 3af673132a
10 changed files with 523 additions and 454 deletions
+65 -43
View File
@@ -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);
}
}
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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";
+58 -59
View File
@@ -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()