Skip to content

Commit

Permalink
Merge pull request #1350 from fluidvanadium/expand_confirmation_status
Browse files Browse the repository at this point in the history
Expand confirmation status
  • Loading branch information
zancas authored Aug 30, 2024
2 parents 5983d57 + 205d3a5 commit df09a3d
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 59 deletions.
6 changes: 3 additions & 3 deletions libtonode-tests/tests/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ mod fast {
.find(|tx| tx.value() == 20_000)
.unwrap()
.status(),
ConfirmationStatus::Pending(BlockHeight::from_u32(5)) // FIXME: mempool blockheight is at chain hieght instead of chain height + 1
ConfirmationStatus::Mempool(BlockHeight::from_u32(5)) // FIXME: mempool blockheight is at chain hieght instead of chain height + 1
);

increase_height_and_wait_for_client(&regtest_manager, &recipient, 1)
Expand Down Expand Up @@ -1187,7 +1187,7 @@ mod slow {
.fee(Some(20_000))
.orchard_notes(vec![OrchardNoteSummary::from_parts(
99_960_000,
SpendSummary::PendingSpent(
SpendSummary::TransmittedSpent(
utils::conversion::txid_from_hex_encoded_str(TEST_TXID).unwrap(),
),
Some(0),
Expand All @@ -1208,7 +1208,7 @@ mod slow {
let first_send_to_transparent = 20_000;
let summary_external_transparent = TransactionSummaryBuilder::new()
.blockheight(BlockHeight::from_u32(7))
.status(ConfirmationStatus::Pending(BlockHeight::from_u32(7)))
.status(ConfirmationStatus::Mempool(BlockHeight::from_u32(7)))
.datetime(0)
.txid(utils::conversion::txid_from_hex_encoded_str(TEST_TXID).unwrap())
.value(first_send_to_transparent)
Expand Down
88 changes: 64 additions & 24 deletions zingo-status/src/confirmation_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ use zcash_primitives::consensus::BlockHeight;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ConfirmationStatus {
/// The transaction is pending confirmation to the zcash blockchain. It may be waiting in the mempool.
/// The transaction has been sent to the zcash blockchain. It could be in the mempool, but if
/// it's known to be, it will be Mempool instead,
/// The BlockHeight is the 1 + the height of the chain as the transaction was broadcast, i.e. the target height.
Pending(BlockHeight),
Transmitted(BlockHeight),

/// The transaction is known to be or have been in the mempool.
/// The BlockHeight is the 1 + the height of the chain as the transaction was broadcast, i.e. the target height.
Mempool(BlockHeight),

/// The transaction has been included in at-least one block mined to the zcash blockchain.
/// The height of a confirmed block that contains the transaction.
Confirmed(BlockHeight),
Expand All @@ -19,29 +25,55 @@ impl ConfirmationStatus {
/// Converts from a blockheight and `pending`. pending is deprecated and is only needed in loading from save.
pub fn from_blockheight_and_pending_bool(blockheight: BlockHeight, pending: bool) -> Self {
if pending {
Self::Pending(blockheight)
Self::Transmitted(blockheight)
} else {
Self::Confirmed(blockheight)
}
}

/// A wrapper matching the Pending case.
/// Is pending/unconfirmed. Use is_transmitted/is_mempool where possible
pub fn is_pending(&self) -> bool {
match self {
ConfirmationStatus::Transmitted(_) | ConfirmationStatus::Mempool(_) => true,
ConfirmationStatus::Confirmed(_) => false,
}
}

/// A wrapper matching the Transmitted case.
/// # Examples
///
/// ```
/// use zingo_status::confirmation_status::ConfirmationStatus;
/// use zcash_primitives::consensus::BlockHeight;
///
/// let status = ConfirmationStatus::Pending(10.into());
/// assert_eq!(status.is_pending(), true);
/// let status = ConfirmationStatus::Transmitted(10.into());
/// assert_eq!(status.is_transmitted(), true);
/// assert_eq!(status.is_confirmed(), false);
///
/// let status = ConfirmationStatus::Confirmed(10.into());
/// assert_eq!(status.is_pending(), false);
/// assert_eq!(status.is_transmitted(), false);
/// assert_eq!(status.is_confirmed(), true);
/// ```
pub fn is_pending(&self) -> bool {
matches!(self, Self::Pending(_))
pub fn is_transmitted(&self) -> bool {
matches!(self, Self::Transmitted(_))
}
/// A wrapper matching the Mempool case.
/// # Examples
///
/// ```
/// use zingo_status::confirmation_status::ConfirmationStatus;
/// use zcash_primitives::consensus::BlockHeight;
///
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_mempool(), true);
/// assert_eq!(status.is_confirmed(), false);
///
/// let status = ConfirmationStatus::Confirmed(10.into());
/// assert_eq!(status.is_mempool(), false);
/// assert_eq!(status.is_confirmed(), true);
/// ```
pub fn is_mempool(&self) -> bool {
matches!(self, Self::Mempool(_))
}

/// A wrapper matching the Confirmed case.
Expand All @@ -51,7 +83,7 @@ impl ConfirmationStatus {
/// use zingo_status::confirmation_status::ConfirmationStatus;
/// use zcash_primitives::consensus::BlockHeight;
///
/// let status = ConfirmationStatus::Pending(10.into());
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_confirmed(), false);
/// assert_eq!(status.is_pending(), true);
///
Expand All @@ -73,7 +105,7 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(10.into());
/// assert_eq!(status.is_confirmed_after_or_at(&9.into()), true);
///
/// let status = ConfirmationStatus::Pending(10.into());
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_confirmed_after_or_at(&10.into()), false);
///
/// let status = ConfirmationStatus::Confirmed(10.into());
Expand All @@ -96,7 +128,7 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(10.into());
/// assert_eq!(status.is_confirmed_before_or_at(&9.into()), false);
///
/// let status = ConfirmationStatus::Pending(10.into());
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_confirmed_before_or_at(&10.into()), false);
///
/// let status = ConfirmationStatus::Confirmed(10.into());
Expand Down Expand Up @@ -144,15 +176,17 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(10.into());
/// assert_eq!(status.is_pending_after_or_at(&9.into()), false);
///
/// let status = ConfirmationStatus::Pending(10.into());
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_pending_after_or_at(&10.into()), true);
///
/// let status = ConfirmationStatus::Pending(10.into());
/// let status = ConfirmationStatus::Mempool(10.into());
/// assert_eq!(status.is_pending_after_or_at(&11.into()), false);
/// ```
pub fn is_pending_after_or_at(&self, comparison_height: &BlockHeight) -> bool {
match self {
Self::Pending(self_height) => self_height >= comparison_height,
Self::Transmitted(self_height) | Self::Mempool(self_height) => {
self_height >= comparison_height
}
_ => false,
}
}
Expand All @@ -167,15 +201,17 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(16.into());
/// assert_eq!(status.is_pending_before(&15.into()), false);
///
/// let status = ConfirmationStatus::Pending(12.into());
/// let status = ConfirmationStatus::Mempool(12.into());
/// assert_eq!(status.is_pending_before(&13.into()), true);
///
/// let status = ConfirmationStatus::Pending(14.into());
/// let status = ConfirmationStatus::Mempool(14.into());
/// assert_eq!(status.is_pending_before(&14.into()), false);
/// ```
pub fn is_pending_before(&self, comparison_height: &BlockHeight) -> bool {
match self {
Self::Pending(self_height) => self_height < comparison_height,
Self::Transmitted(self_height) | Self::Mempool(self_height) => {
self_height < comparison_height
}
Self::Confirmed(_) => false,
}
}
Expand All @@ -190,7 +226,7 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(16.into());
/// assert_eq!(status.get_confirmed_height(), Some(16.into()));
///
/// let status = ConfirmationStatus::Pending(15.into());
/// let status = ConfirmationStatus::Mempool(15.into());
/// assert_eq!(status.get_confirmed_height(), None);
/// ```
pub fn get_confirmed_height(&self) -> Option<BlockHeight> {
Expand All @@ -210,12 +246,12 @@ impl ConfirmationStatus {
/// let status = ConfirmationStatus::Confirmed(16.into());
/// assert_eq!(status.get_pending_height(), None);
///
/// let status = ConfirmationStatus::Pending(15.into());
/// let status = ConfirmationStatus::Mempool(15.into());
/// assert_eq!(status.get_pending_height(), Some(15.into()));
/// ```
pub fn get_pending_height(&self) -> Option<BlockHeight> {
match self {
Self::Pending(self_height) => Some(*self_height),
Self::Mempool(self_height) | Self::Transmitted(self_height) => Some(*self_height),
_ => None,
}
}
Expand All @@ -231,7 +267,8 @@ impl ConfirmationStatus {
/// ```
pub fn get_height(&self) -> BlockHeight {
match self {
Self::Pending(self_height) => *self_height,
Self::Mempool(self_height) => *self_height,
Self::Transmitted(self_height) => *self_height,
Self::Confirmed(self_height) => *self_height,
}
}
Expand All @@ -240,8 +277,11 @@ impl ConfirmationStatus {
impl std::fmt::Display for ConfirmationStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Pending(_) => {
write!(f, "pending")
Self::Transmitted(_) => {
write!(f, "transmitted")
}
Self::Mempool(_) => {
write!(f, "mempool")
}
Self::Confirmed(_) => {
write!(f, "confirmed")
Expand Down
2 changes: 1 addition & 1 deletion zingolib/src/lightclient/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl LightClient {
{
let price = price.read().await.clone();
//debug!("Mempool attempting to scan {}", tx.txid());
let status = ConfirmationStatus::Pending(BlockHeight::from_u32(
let status = ConfirmationStatus::Mempool(BlockHeight::from_u32(
rtransaction.height as u32,
));

Expand Down
6 changes: 5 additions & 1 deletion zingolib/src/testutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ fn check_spend_status_equality(first: SpendSummary, second: SpendSummary) -> boo
(first, second),
(SpendSummary::Unspent, SpendSummary::Unspent)
| (SpendSummary::Spent(_), SpendSummary::Spent(_))
| (SpendSummary::PendingSpent(_), SpendSummary::PendingSpent(_))
| (
SpendSummary::TransmittedSpent(_),
SpendSummary::TransmittedSpent(_)
)
| (SpendSummary::MempoolSpent(_), SpendSummary::MempoolSpent(_))
)
}

Expand Down
10 changes: 5 additions & 5 deletions zingolib/src/testutils/chain_generics/with_assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ where
sender,
&proposal,
&txids,
ConfirmationStatus::Pending(send_height.into()),
ConfirmationStatus::Transmitted(send_height.into()),
)
.await;

Expand All @@ -63,7 +63,7 @@ where
sender,
&proposal,
&txids,
ConfirmationStatus::Pending(send_height.into()),
ConfirmationStatus::Mempool(send_height.into()),
)
.await;

Expand All @@ -75,7 +75,7 @@ where
recipient,
&proposal,
&txids,
ConfirmationStatus::Pending(send_height.into()),
ConfirmationStatus::Mempool(send_height.into()),
)
.await;
}
Expand Down Expand Up @@ -126,7 +126,7 @@ where
client,
&proposal,
&txids,
ConfirmationStatus::Pending(send_height.into()),
ConfirmationStatus::Transmitted(send_height.into()),
)
.await;

Expand All @@ -137,7 +137,7 @@ where
client,
&proposal,
&txids,
ConfirmationStatus::Pending(send_height.into()),
ConfirmationStatus::Mempool(send_height.into()),
)
.await;
}
Expand Down
18 changes: 13 additions & 5 deletions zingolib/src/wallet/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1738,8 +1738,11 @@ pub mod summaries {
/// Output is not spent.
Unspent,
/// Output is pending spent.
/// The transaction consuming this output is pending.
PendingSpent(TxId),
/// The transaction consuming this output has been transmitted.
TransmittedSpent(TxId),
/// Output is pending spent.
/// The transaction consuming this output has been detected in the mempool.
MempoolSpent(TxId),
/// Output is spent.
/// The transaction consuming this output is confirmed.
Spent(TxId),
Expand All @@ -1750,7 +1753,11 @@ pub mod summaries {
pub fn from_spend(spend: &Option<(TxId, ConfirmationStatus)>) -> Self {
match spend {
None => SpendSummary::Unspent,
Some((txid, ConfirmationStatus::Pending(_))) => SpendSummary::PendingSpent(*txid),
Some((txid, ConfirmationStatus::Transmitted(_))) => {
SpendSummary::TransmittedSpent(*txid)
}

Some((txid, ConfirmationStatus::Mempool(_))) => SpendSummary::MempoolSpent(*txid),
Some((txid, ConfirmationStatus::Confirmed(_))) => SpendSummary::Spent(*txid),
}
}
Expand All @@ -1760,8 +1767,9 @@ pub mod summaries {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SpendSummary::Unspent => write!(f, "unspent"),
SpendSummary::PendingSpent(txid) => write!(f, "pending spent in {}", txid),
SpendSummary::Spent(txid) => write!(f, "spent in {}", txid),
SpendSummary::TransmittedSpent(txid) => write!(f, "transmitted: spent in {}", txid),
SpendSummary::Spent(txid) => write!(f, "confirmed: spent in {}", txid),
SpendSummary::MempoolSpent(txid) => write!(f, "mempool: spent in {}", txid),
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions zingolib/src/wallet/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ mod tests {
.clone(),
)
.build();
let pending_tx_record = TransactionRecordBuilder::default()
.status(ConfirmationStatus::Pending(95.into()))
let mempool_tx_record = TransactionRecordBuilder::default()
.status(ConfirmationStatus::Mempool(95.into()))
.transparent_outputs(TransparentOutputBuilder::default())
.sapling_notes(SaplingNoteBuilder::default())
.orchard_notes(OrchardNoteBuilder::default())
Expand All @@ -383,7 +383,7 @@ mod tests {
.insert_transaction_record(confirmed_tx_record);
tx_map
.transaction_records_by_id
.insert_transaction_record(pending_tx_record);
.insert_transaction_record(mempool_tx_record);
}

assert_eq!(
Expand Down
4 changes: 2 additions & 2 deletions zingolib/src/wallet/notes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ pub mod tests {
use super::query::{OutputPoolQuery, OutputSpendStatusQuery};

use zingo_status::confirmation_status::ConfirmationStatus::Confirmed;
use zingo_status::confirmation_status::ConfirmationStatus::Pending;
use zingo_status::confirmation_status::ConfirmationStatus::Mempool;

#[test]
fn note_queries() {
let confirmed_spend = Some((default_txid(), Confirmed(112358.into())));
let pending_spend = Some((default_txid(), Pending(112357.into())));
let pending_spend = Some((default_txid(), Mempool(112357.into())));

let transparent_unspent_note = TransparentOutputBuilder::default().build();
let transparent_pending_spent_note = TransparentOutputBuilder::default()
Expand Down
3 changes: 1 addition & 2 deletions zingolib/src/wallet/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,10 @@ impl LightWallet {
let serverz_transaction_id =
broadcast_fn(raw_transaction.clone().into_boxed_slice()).await?;

// Add this transaction to the mempool structure
{
let price = self.price.read().await.clone();

let status = ConfirmationStatus::Pending(submission_height);
let status = ConfirmationStatus::Transmitted(submission_height);
self.transaction_context
.scan_full_tx(
transaction,
Expand Down
1 change: 1 addition & 0 deletions zingolib/src/wallet/transaction_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ mod decrypt_transaction {
note.clone(),
to,
output_index,
status.is_mempool(),
);
} else {
self.transaction_metadata_set
Expand Down
Loading

0 comments on commit df09a3d

Please sign in to comment.