Skip to content

Commit

Permalink
feat!: update status (#6008)
Browse files Browse the repository at this point in the history
Description
---
Changes statuses of coinbase transactions and one-sided transactions

Motivation and Context
---
Transactions now show as one-sided or coinbase, not Faux anymore. This
is more inline of what they are and shows more information to the user.

How Has This Been Tested?
---
manual + unit tests

Breaking Changes
---
Wallet database changes, and requires recovery to keep existing
database.
  • Loading branch information
SWvheerden committed Dec 6, 2023
1 parent 6d25ded commit e19ce15
Show file tree
Hide file tree
Showing 19 changed files with 284 additions and 164 deletions.
8 changes: 6 additions & 2 deletions applications/minotari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,17 @@ enum TransactionStatus {
// The transaction was rejected by the mempool
TRANSACTION_STATUS_REJECTED = 7;
// This is faux transaction mainly for one-sided transaction outputs or wallet recovery outputs have been found
TRANSACTION_STATUS_FAUX_UNCONFIRMED = 8;
TRANSACTION_STATUS_ONE_SIDED_UNCONFIRMED = 8;
// All Imported and FauxUnconfirmed transactions will end up with this status when the outputs have been confirmed
TRANSACTION_STATUS_FAUX_CONFIRMED = 9;
TRANSACTION_STATUS_ONE_SIDED_CONFIRMED = 9;
// This transaction is still being queued for sending
TRANSACTION_STATUS_QUEUED = 10;
// The transaction was not found by the wallet its in transaction database
TRANSACTION_STATUS_NOT_FOUND = 11;
// This is Coinbase transaction that is detected from chain
TRANSACTION_STATUS_COINBASE_UNCONFIRMED = 12;
// This is Coinbase transaction that is detected from chain
TRANSACTION_STATUS_COINBASE_CONFIRMED = 13;
}

message GetCompletedTransactionsRequest { }
Expand Down
6 changes: 4 additions & 2 deletions applications/minotari_app_grpc/src/conversions/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,10 @@ impl From<TransactionStatus> for grpc::TransactionStatus {
Coinbase => grpc::TransactionStatus::Coinbase,
MinedConfirmed => grpc::TransactionStatus::MinedConfirmed,
Rejected => grpc::TransactionStatus::Rejected,
FauxUnconfirmed => grpc::TransactionStatus::FauxUnconfirmed,
FauxConfirmed => grpc::TransactionStatus::FauxConfirmed,
OneSidedUnconfirmed => grpc::TransactionStatus::OneSidedUnconfirmed,
OneSidedConfirmed => grpc::TransactionStatus::OneSidedConfirmed,
CoinbaseUnconfirmed => grpc::TransactionStatus::CoinbaseUnconfirmed,
CoinbaseConfirmed => grpc::TransactionStatus::CoinbaseConfirmed,
Queued => grpc::TransactionStatus::Queued,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,8 +682,8 @@ impl wallet_server::Wallet for WalletGrpcServer {
}
},
ReceivedFinalizedTransaction(tx_id) => handle_completed_tx(tx_id, RECEIVED, &mut transaction_service, &mut sender).await,
TransactionMinedUnconfirmed{tx_id, num_confirmations: _, is_valid: _} | FauxTransactionUnconfirmed{tx_id, num_confirmations: _, is_valid: _}=> handle_completed_tx(tx_id, CONFIRMATION, &mut transaction_service, &mut sender).await,
TransactionMined{tx_id, is_valid: _} | FauxTransactionConfirmed{tx_id, is_valid: _} => handle_completed_tx(tx_id, MINED, &mut transaction_service, &mut sender).await,
TransactionMinedUnconfirmed{tx_id, num_confirmations: _, is_valid: _} | DetectedTransactionUnconfirmed{tx_id, num_confirmations: _, is_valid: _}=> handle_completed_tx(tx_id, CONFIRMATION, &mut transaction_service, &mut sender).await,
TransactionMined{tx_id, is_valid: _} | DetectedTransactionConfirmed{tx_id, is_valid: _} => handle_completed_tx(tx_id, MINED, &mut transaction_service, &mut sender).await,
TransactionCancelled(tx_id, _) => {
match transaction_service.get_any_transaction(tx_id).await{
Ok(Some(wallet_tx)) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl WalletEventMonitor {
).await;
},
TransactionEvent::TransactionMinedUnconfirmed{tx_id, num_confirmations, is_valid: _} |
TransactionEvent::FauxTransactionUnconfirmed{tx_id, num_confirmations, is_valid: _}=> {
TransactionEvent::DetectedTransactionUnconfirmed{tx_id, num_confirmations, is_valid: _}=> {
self.trigger_confirmations_refresh(tx_id, num_confirmations).await;
self.trigger_tx_state_refresh(tx_id).await;
self.trigger_balance_refresh();
Expand All @@ -123,7 +123,7 @@ impl WalletEventMonitor {
).await;
},
TransactionEvent::TransactionMined{tx_id, is_valid: _} |
TransactionEvent::FauxTransactionConfirmed{tx_id, is_valid: _}=> {
TransactionEvent::DetectedTransactionConfirmed{tx_id, is_valid: _}=> {
self.trigger_confirmations_cleanup(tx_id).await;
self.trigger_tx_state_refresh(tx_id).await;
self.trigger_balance_refresh();
Expand Down
126 changes: 99 additions & 27 deletions base_layer/common_types/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,96 @@ pub use crate::tx_id::TxId;
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TransactionStatus {
/// This transaction has been completed between the parties but has not been broadcast to the base layer network.
Completed,
Completed = 0,
/// This transaction has been broadcast to the base layer network and is currently in one or more base node
/// mempools.
Broadcast,
Broadcast = 1,
/// This transaction has been mined and included in a block.
MinedUnconfirmed,
MinedUnconfirmed = 2,
/// This transaction was generated as part of importing a spendable unblinded UTXO
Imported,
Imported = 3,
/// This transaction is still being negotiated by the parties
#[default]
Pending,
Pending = 4,
/// This is a created Coinbase Transaction
Coinbase,
Coinbase = 5,
/// This transaction is mined and confirmed at the current base node's height
MinedConfirmed,
MinedConfirmed = 6,
/// This transaction was Rejected by the mempool
Rejected,
/// This is faux transaction mainly for one-sided transaction outputs or wallet recovery outputs have been found
FauxUnconfirmed,
/// All Imported and FauxUnconfirmed transactions will end up with this status when the outputs have been confirmed
FauxConfirmed,
Rejected = 7,
/// This transaction import status is used when a one-sided transaction has been scanned but is unconfirmed
OneSidedUnconfirmed = 8,
/// This transaction import status is used when a one-sided transaction has been scanned and confirmed
OneSidedConfirmed = 9,
/// This transaction is still being queued for initial sending
Queued,
Queued = 10,
/// This transaction import status is used when a one-sided transaction has been scanned but is unconfirmed
CoinbaseUnconfirmed = 11,
/// This transaction import status is used when a one-sided transaction has been scanned and confirmed
CoinbaseConfirmed = 12,
}

impl TransactionStatus {
pub fn is_faux(&self) -> bool {
pub fn is_imported_from_chain(&self) -> bool {
matches!(
self,
TransactionStatus::Imported | TransactionStatus::FauxUnconfirmed | TransactionStatus::FauxConfirmed
TransactionStatus::Imported | TransactionStatus::OneSidedUnconfirmed | TransactionStatus::OneSidedConfirmed
)
}

pub fn is_coinbase(&self) -> bool {
matches!(
self,
TransactionStatus::CoinbaseUnconfirmed | TransactionStatus::CoinbaseConfirmed
)
}

pub fn is_confirmed(&self) -> bool {
matches!(
self,
TransactionStatus::OneSidedConfirmed |
TransactionStatus::CoinbaseConfirmed |
TransactionStatus::MinedConfirmed
)
}

pub fn mined_confirm(&self) -> Self {
match self {
TransactionStatus::Completed |
TransactionStatus::Broadcast |
TransactionStatus::Pending |
TransactionStatus::Coinbase |
TransactionStatus::Rejected |
TransactionStatus::Queued |
TransactionStatus::MinedUnconfirmed |
TransactionStatus::MinedConfirmed => TransactionStatus::MinedConfirmed,
TransactionStatus::Imported |
TransactionStatus::OneSidedUnconfirmed |
TransactionStatus::OneSidedConfirmed => TransactionStatus::OneSidedConfirmed,
TransactionStatus::CoinbaseConfirmed | TransactionStatus::CoinbaseUnconfirmed => {
TransactionStatus::CoinbaseConfirmed
},
}
}

pub fn mined_unconfirm(&self) -> Self {
match self {
TransactionStatus::Completed |
TransactionStatus::Broadcast |
TransactionStatus::Pending |
TransactionStatus::Coinbase |
TransactionStatus::Rejected |
TransactionStatus::Queued |
TransactionStatus::MinedUnconfirmed |
TransactionStatus::MinedConfirmed => TransactionStatus::MinedUnconfirmed,
TransactionStatus::Imported |
TransactionStatus::OneSidedUnconfirmed |
TransactionStatus::OneSidedConfirmed => TransactionStatus::OneSidedUnconfirmed,
TransactionStatus::CoinbaseConfirmed | TransactionStatus::CoinbaseUnconfirmed => {
TransactionStatus::CoinbaseUnconfirmed
},
}
}
}

#[derive(Debug, Error)]
Expand All @@ -68,9 +126,11 @@ impl TryFrom<i32> for TransactionStatus {
5 => Ok(TransactionStatus::Coinbase),
6 => Ok(TransactionStatus::MinedConfirmed),
7 => Ok(TransactionStatus::Rejected),
8 => Ok(TransactionStatus::FauxUnconfirmed),
9 => Ok(TransactionStatus::FauxConfirmed),
8 => Ok(TransactionStatus::OneSidedUnconfirmed),
9 => Ok(TransactionStatus::OneSidedConfirmed),
10 => Ok(TransactionStatus::Queued),
11 => Ok(TransactionStatus::CoinbaseUnconfirmed),
12 => Ok(TransactionStatus::CoinbaseConfirmed),
code => Err(TransactionConversionError { code }),
}
}
Expand All @@ -88,8 +148,10 @@ impl Display for TransactionStatus {
TransactionStatus::Pending => write!(f, "Pending"),
TransactionStatus::Coinbase => write!(f, "Coinbase"),
TransactionStatus::Rejected => write!(f, "Rejected"),
TransactionStatus::FauxUnconfirmed => write!(f, "FauxUnconfirmed"),
TransactionStatus::FauxConfirmed => write!(f, "FauxConfirmed"),
TransactionStatus::OneSidedUnconfirmed => write!(f, "One-Sided Unconfirmed"),
TransactionStatus::OneSidedConfirmed => write!(f, "One-Sided Confirmed"),
TransactionStatus::CoinbaseUnconfirmed => write!(f, "Coinbase Unconfirmed"),
TransactionStatus::CoinbaseConfirmed => write!(f, "Coinbase Confirmed"),
TransactionStatus::Queued => write!(f, "Queued"),
}
}
Expand All @@ -100,9 +162,13 @@ pub enum ImportStatus {
/// This transaction import status is used when importing a spendable UTXO
Imported,
/// This transaction import status is used when a one-sided transaction has been scanned but is unconfirmed
FauxUnconfirmed,
OneSidedUnconfirmed,
/// This transaction import status is used when a one-sided transaction has been scanned and confirmed
OneSidedConfirmed,
/// This transaction import status is used when a one-sided transaction has been scanned but is unconfirmed
CoinbaseUnconfirmed,
/// This transaction import status is used when a one-sided transaction has been scanned and confirmed
FauxConfirmed,
CoinbaseConfirmed,
}

impl TryFrom<ImportStatus> for TransactionStatus {
Expand All @@ -111,8 +177,10 @@ impl TryFrom<ImportStatus> for TransactionStatus {
fn try_from(value: ImportStatus) -> Result<Self, Self::Error> {
match value {
ImportStatus::Imported => Ok(TransactionStatus::Imported),
ImportStatus::FauxUnconfirmed => Ok(TransactionStatus::FauxUnconfirmed),
ImportStatus::FauxConfirmed => Ok(TransactionStatus::FauxConfirmed),
ImportStatus::OneSidedUnconfirmed => Ok(TransactionStatus::OneSidedUnconfirmed),
ImportStatus::OneSidedConfirmed => Ok(TransactionStatus::OneSidedConfirmed),
ImportStatus::CoinbaseUnconfirmed => Ok(TransactionStatus::CoinbaseUnconfirmed),
ImportStatus::CoinbaseConfirmed => Ok(TransactionStatus::CoinbaseConfirmed),
}
}
}
Expand All @@ -123,8 +191,10 @@ impl TryFrom<TransactionStatus> for ImportStatus {
fn try_from(value: TransactionStatus) -> Result<Self, Self::Error> {
match value {
TransactionStatus::Imported => Ok(ImportStatus::Imported),
TransactionStatus::FauxUnconfirmed => Ok(ImportStatus::FauxUnconfirmed),
TransactionStatus::FauxConfirmed => Ok(ImportStatus::FauxConfirmed),
TransactionStatus::OneSidedUnconfirmed => Ok(ImportStatus::OneSidedUnconfirmed),
TransactionStatus::OneSidedConfirmed => Ok(ImportStatus::OneSidedConfirmed),
TransactionStatus::CoinbaseUnconfirmed => Ok(ImportStatus::CoinbaseUnconfirmed),
TransactionStatus::CoinbaseConfirmed => Ok(ImportStatus::CoinbaseConfirmed),
_ => Err(TransactionConversionError { code: i32::MAX }),
}
}
Expand All @@ -134,8 +204,10 @@ impl fmt::Display for ImportStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match self {
ImportStatus::Imported => write!(f, "Imported"),
ImportStatus::FauxUnconfirmed => write!(f, "FauxUnconfirmed"),
ImportStatus::FauxConfirmed => write!(f, "FauxConfirmed"),
ImportStatus::OneSidedUnconfirmed => write!(f, "OneSidedUnconfirmed"),
ImportStatus::OneSidedConfirmed => write!(f, "OneSidedConfirmed"),
ImportStatus::CoinbaseUnconfirmed => write!(f, "CoinbaseUnconfirmed"),
ImportStatus::CoinbaseConfirmed => write!(f, "CoinbaseConfirmed"),
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions base_layer/wallet/src/transaction_service/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,12 @@ pub enum TransactionEvent {
TransactionCancelled(TxId, TxCancellationReason),
TransactionBroadcast(TxId),
TransactionImported(TxId),
FauxTransactionUnconfirmed {
DetectedTransactionUnconfirmed {
tx_id: TxId,
num_confirmations: u64,
is_valid: bool,
},
FauxTransactionConfirmed {
DetectedTransactionConfirmed {
tx_id: TxId,
is_valid: bool,
},
Expand Down Expand Up @@ -360,19 +360,19 @@ impl fmt::Display for TransactionEvent {
TransactionEvent::TransactionImported(tx) => {
write!(f, "TransactionImported for {tx}")
},
TransactionEvent::FauxTransactionUnconfirmed {
TransactionEvent::DetectedTransactionUnconfirmed {
tx_id,
num_confirmations,
is_valid,
} => {
write!(
f,
"FauxTransactionUnconfirmed for {tx_id} with num confirmations: {num_confirmations}. is_valid: \
{is_valid}"
"DetectedTransactionUnconfirmed for {tx_id} with num confirmations: {num_confirmations}. \
is_valid: {is_valid}"
)
},
TransactionEvent::FauxTransactionConfirmed { tx_id, is_valid } => {
write!(f, "FauxTransactionConfirmed for {tx_id}. is_valid: {is_valid}")
TransactionEvent::DetectedTransactionConfirmed { tx_id, is_valid } => {
write!(f, "DetectedTransactionConfirmed for {tx_id}. is_valid: {is_valid}")
},
TransactionEvent::TransactionMined { tx_id, is_valid } => {
write!(f, "TransactionMined for {tx_id}. is_valid: {is_valid}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,18 +371,18 @@ where
mined_timestamp,
num_confirmations,
num_confirmations >= self.config.num_confirmations_required,
status.is_faux(),
status,
)
.for_protocol(self.operation_id)?;

if num_confirmations >= self.config.num_confirmations_required {
if status.is_faux() {
self.publish_event(TransactionEvent::FauxTransactionConfirmed { tx_id, is_valid: true })
if status.is_coinbase() || status.is_imported_from_chain() {
self.publish_event(TransactionEvent::DetectedTransactionConfirmed { tx_id, is_valid: true })
} else {
self.publish_event(TransactionEvent::TransactionMined { tx_id, is_valid: true })
}
} else if status.is_faux() {
self.publish_event(TransactionEvent::FauxTransactionUnconfirmed {
} else if status.is_coinbase() || status.is_imported_from_chain() {
self.publish_event(TransactionEvent::DetectedTransactionUnconfirmed {
tx_id,
num_confirmations,
is_valid: true,
Expand Down
18 changes: 11 additions & 7 deletions base_layer/wallet/src/transaction_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ use crate::{
models::{CompletedTransaction, TxCancellationReason},
},
tasks::{
check_faux_transaction_status::check_faux_transactions,
check_faux_transaction_status::check_detected_transactions,
send_finalized_transaction::send_finalized_transaction_message,
send_transaction_cancelled::send_transaction_cancelled_message,
send_transaction_reply::send_transaction_reply,
Expand Down Expand Up @@ -928,7 +928,7 @@ where
None => 0u64,
};
let event_publisher = self.event_publisher.clone();
tokio::spawn(check_faux_transactions(
tokio::spawn(check_detected_transactions(
output_manager_handle,
db,
event_publisher,
Expand Down Expand Up @@ -2813,12 +2813,16 @@ where
)?;
let transaction_event = match import_status {
ImportStatus::Imported => TransactionEvent::TransactionImported(tx_id),
ImportStatus::FauxUnconfirmed => TransactionEvent::FauxTransactionUnconfirmed {
tx_id,
num_confirmations: 0,
is_valid: true,
ImportStatus::OneSidedUnconfirmed | ImportStatus::CoinbaseUnconfirmed => {
TransactionEvent::DetectedTransactionUnconfirmed {
tx_id,
num_confirmations: 0,
is_valid: true,
}
},
ImportStatus::OneSidedConfirmed | ImportStatus::CoinbaseConfirmed => {
TransactionEvent::DetectedTransactionConfirmed { tx_id, is_valid: true }
},
ImportStatus::FauxConfirmed => TransactionEvent::FauxTransactionConfirmed { tx_id, is_valid: true },
};
let _size = self.event_publisher.send(Arc::new(transaction_event)).map_err(|e| {
trace!(
Expand Down
Loading

0 comments on commit e19ce15

Please sign in to comment.