[chain_redesign] BlockId should not implement Anchor

If `BlockId` implements `Anchor`, the meaning is ambiguous. We cannot
tell whether it means the tx is anchors at the block, or whether it also
means the tx is confirmed at that block.

Instead, `ConfirmationHeightAnchor` and `ConfirmationTimeAnchor` structs
are introduced as non-ambiguous `Anchor` implementations.

Additionally, `TxGraph::relevant_heights` is removed because it is also
ambiguous. What heights are deemed relevant? A simpler and more flexible
method `TxGraph::all_anchors` is introduced instead.
This commit is contained in:
志宇
2023-05-03 16:03:23 +08:00
parent 4ae727a1fb
commit 2ccc116eda
4 changed files with 159 additions and 172 deletions

View File

@@ -160,12 +160,6 @@ impl Default for BlockId {
}
}
impl Anchor for BlockId {
fn anchor_block(&self) -> BlockId {
*self
}
}
impl From<(u32, BlockHash)> for BlockId {
fn from((height, hash): (u32, BlockHash)) -> Self {
Self { height, hash }
@@ -187,6 +181,58 @@ impl From<(&u32, &BlockHash)> for BlockId {
}
}
/// An [`Anchor`] implementation that also records the exact confirmation height of the transaction.
#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(crate = "serde_crate")
)]
pub struct ConfirmationHeightAnchor {
/// The anchor block.
pub anchor_block: BlockId,
/// The exact confirmation height of the transaction.
///
/// It is assumed that this value is never larger than the height of the anchor block.
pub confirmation_height: u32,
}
impl Anchor for ConfirmationHeightAnchor {
fn anchor_block(&self) -> BlockId {
self.anchor_block
}
fn confirmation_height_upper_bound(&self) -> u32 {
self.confirmation_height
}
}
/// An [`Anchor`] implementation that also records the exact confirmation time and height of the
/// transaction.
#[derive(Debug, Default, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(crate = "serde_crate")
)]
pub struct ConfirmationTimeAnchor {
/// The anchor block.
pub anchor_block: BlockId,
pub confirmation_height: u32,
pub confirmation_time: u64,
}
impl Anchor for ConfirmationTimeAnchor {
fn anchor_block(&self) -> BlockId {
self.anchor_block
}
fn confirmation_height_upper_bound(&self) -> u32 {
self.confirmation_height
}
}
/// A `TxOut` with as much data as we can retrieve about it
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FullTxOut<P> {

View File

@@ -349,6 +349,11 @@ impl<A> TxGraph<A> {
.filter(move |(_, conflicting_txid)| *conflicting_txid != txid)
}
/// Get all transaction anchors known by [`TxGraph`].
pub fn all_anchors(&self) -> &BTreeSet<(A, Txid)> {
&self.anchors
}
/// Whether the graph has any transactions or outputs in it.
pub fn is_empty(&self) -> bool {
self.txs.is_empty()
@@ -592,21 +597,6 @@ impl<A: Clone + Ord> TxGraph<A> {
}
impl<A: Anchor> TxGraph<A> {
/// Get all heights that are relevant to the graph.
pub fn relevant_heights(&self) -> impl Iterator<Item = u32> + '_ {
let mut last_height = Option::<u32>::None;
self.anchors
.iter()
.map(|(a, _)| a.anchor_block().height)
.filter(move |&height| {
let is_unique = Some(height) != last_height;
if is_unique {
last_height = Some(height);
}
is_unique
})
}
/// Get the position of the transaction in `chain` with tip `chain_tip`.
///
/// If the given transaction of `txid` does not exist in the chain of `chain_tip`, `None` is