mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-20 07:28:11 -07:00
84 lines
3.2 KiB
Rust
84 lines
3.2 KiB
Rust
use brk_types::{FundedAddrData, Height, OutputType};
|
|
|
|
use crate::distribution::{
|
|
addr::{AddrReceivePreState, AddrSendPreState, AddrTypeToAddrCount, AddrTypeToSupply},
|
|
block::TrackingStatus,
|
|
};
|
|
|
|
use super::ExposedAddrVecs;
|
|
|
|
/// Runtime running totals for exposed-addr tracking. Mirrors the persistent
|
|
/// fields of [`ExposedAddrVecs`]: funded count, total count, funded supply.
|
|
/// Recovered from disk at the start of a block-loop run.
|
|
#[derive(Debug, Default)]
|
|
pub struct ExposedAddrState {
|
|
pub funded: AddrTypeToAddrCount,
|
|
pub total: AddrTypeToAddrCount,
|
|
pub supply: AddrTypeToSupply,
|
|
}
|
|
|
|
impl ExposedAddrState {
|
|
/// Apply exposed-addr updates for a received output, AFTER the receive
|
|
/// has mutated `addr_data`. `pre` is the snapshot taken before the mutation.
|
|
#[inline]
|
|
pub(crate) fn on_receive(
|
|
&mut self,
|
|
output_type: OutputType,
|
|
addr_data: &FundedAddrData,
|
|
pre: &AddrReceivePreState,
|
|
status: TrackingStatus,
|
|
) {
|
|
// Pubkey-exposure state is unchanged by a receive, so `pre.was_pubkey_exposed`
|
|
// equals the post-receive value.
|
|
if !pre.was_funded && pre.was_pubkey_exposed {
|
|
*self.funded.get_mut_unwrap(output_type) += 1;
|
|
}
|
|
// Total for pk-exposed-at-funding types fires here on first receive.
|
|
// Other types fire on first spend in [`Self::on_send`].
|
|
if output_type.pubkey_exposed_at_funding() && matches!(status, TrackingStatus::New) {
|
|
*self.total.get_mut_unwrap(output_type) += 1;
|
|
}
|
|
let after = addr_data.exposed_supply_contribution(output_type);
|
|
self.supply
|
|
.apply_delta(output_type, pre.exposed_contribution, after);
|
|
}
|
|
|
|
/// Apply exposed-addr updates for a spent UTXO, AFTER the send has mutated
|
|
/// `addr_data`. `pre` is the snapshot taken before the mutation.
|
|
#[inline]
|
|
pub(crate) fn on_send(
|
|
&mut self,
|
|
output_type: OutputType,
|
|
addr_data: &FundedAddrData,
|
|
pre: &AddrSendPreState,
|
|
will_be_empty: bool,
|
|
) {
|
|
let after = addr_data.exposed_supply_contribution(output_type);
|
|
self.supply
|
|
.apply_delta(output_type, pre.exposed_contribution, after);
|
|
// First-ever pubkey exposure. Non-pk-exposed types fire on first spend.
|
|
// Pk-exposed types never fire here (was already exposed at first receive).
|
|
if !pre.was_pubkey_exposed {
|
|
*self.total.get_mut_unwrap(output_type) += 1;
|
|
if !will_be_empty {
|
|
*self.funded.get_mut_unwrap(output_type) += 1;
|
|
}
|
|
}
|
|
// Leaving the funded exposed set: was in it iff pubkey was exposed pre-spend.
|
|
if will_be_empty && pre.was_pubkey_exposed {
|
|
*self.funded.get_mut_unwrap(output_type) -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<(&ExposedAddrVecs, Height)> for ExposedAddrState {
|
|
#[inline]
|
|
fn from((vecs, starting_height): (&ExposedAddrVecs, Height)) -> Self {
|
|
Self {
|
|
funded: AddrTypeToAddrCount::from((&vecs.count.funded, starting_height)),
|
|
total: AddrTypeToAddrCount::from((&vecs.count.total, starting_height)),
|
|
supply: AddrTypeToSupply::from((&vecs.supply, starting_height)),
|
|
}
|
|
}
|
|
}
|