Skip to content

Commit 3a2fd08

Browse files
committed
Confirmed tx should not be marked as conflicted
1 parent 7281875 commit 3a2fd08

File tree

3 files changed

+393
-38
lines changed

3 files changed

+393
-38
lines changed

test/functional/wallet_conflict.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ async def async_test(self):
198198

199199
# check we cannot abandon an already confirmed transaction
200200
assert_in("Success", await wallet.select_account(1))
201-
assert_in("Cannot abandon a transaction in Confirmed at height 6", await wallet.abandon_transaction(new_transfer_tx_id))
201+
assert_in("Cannot change a transaction's state from Confirmed", await wallet.abandon_transaction(new_transfer_tx_id))
202202

203203

204204

wallet/src/account/output_cache/mod.rs

+27-22
Original file line numberDiff line numberDiff line change
@@ -689,9 +689,6 @@ impl OutputCache {
689689
confirmed_tx: &Transaction,
690690
block_id: Id<GenBlock>,
691691
) -> WalletResult<Vec<Id<Transaction>>> {
692-
// Collect all conflicting txs
693-
let mut conflicting_txs = vec![];
694-
695692
let mut frozen_token_id: Option<TokenId> = None;
696693
let mut confirmed_account_nonce: Option<(AccountType, AccountNonce)> = None;
697694

@@ -722,14 +719,15 @@ impl OutputCache {
722719
}
723720
}
724721

725-
if frozen_token_id.is_some() | confirmed_account_nonce.is_some() {
722+
// Collect all conflicting txs
723+
let mut conflicting_txs = vec![];
724+
725+
if frozen_token_id.is_some() || confirmed_account_nonce.is_some() {
726726
for unconfirmed in self.unconfirmed_descendants.keys() {
727727
if let Some(frozen_token_id) = frozen_token_id {
728728
let unconfirmed_tx = self.txs.get(unconfirmed).expect("must be present");
729729
if self.uses_token(unconfirmed_tx, &frozen_token_id) {
730-
let unconfirmed_tx =
731-
self.txs.get_mut(unconfirmed).expect("must be present");
732-
if let WalletTx::Tx(ref mut tx) = unconfirmed_tx {
730+
if let WalletTx::Tx(tx) = unconfirmed_tx {
733731
conflicting_txs.push(tx.get_transaction().get_id());
734732
}
735733
}
@@ -743,9 +741,7 @@ impl OutputCache {
743741
confirmed_account,
744742
confirmed_account_nonce,
745743
) {
746-
let unconfirmed_tx =
747-
self.txs.get_mut(unconfirmed).expect("must be present");
748-
if let WalletTx::Tx(ref mut tx) = unconfirmed_tx {
744+
if let WalletTx::Tx(tx) = unconfirmed_tx {
749745
conflicting_txs.push(tx.get_transaction().get_id());
750746
}
751747
}
@@ -755,11 +751,16 @@ impl OutputCache {
755751

756752
// Remove all descendants of conflicting txs
757753
let mut conflicting_txs_with_descendants = vec![];
754+
758755
for conflicting_tx in conflicting_txs {
759-
let descendants =
760-
self.remove_descendants_and_mark_as(conflicting_tx, TxState::Conflicted(block_id))?;
756+
if conflicting_tx != confirmed_tx.get_id() {
757+
let descendants = self.remove_descendants_and_mark_as(
758+
conflicting_tx,
759+
TxState::Conflicted(block_id),
760+
)?;
761761

762-
conflicting_txs_with_descendants.extend(descendants.into_iter());
762+
conflicting_txs_with_descendants.extend(descendants.into_iter());
763+
}
763764
}
764765

765766
Ok(conflicting_txs_with_descendants)
@@ -828,8 +829,11 @@ impl OutputCache {
828829
| TxState::Abandoned => true,
829830
TxState::Confirmed(_, _, _) => false,
830831
};
832+
831833
if is_unconfirmed && !already_present {
832834
self.unconfirmed_descendants.insert(tx_id.clone(), BTreeSet::new());
835+
} else {
836+
self.unconfirmed_descendants.remove(&tx_id);
833837
}
834838

835839
self.update_inputs(&tx, is_unconfirmed, &tx_id, already_present)?;
@@ -944,13 +948,14 @@ impl OutputCache {
944948
match input {
945949
TxInput::Utxo(outpoint) => {
946950
self.consumed.insert(outpoint.clone(), tx.state());
947-
if is_unconfirmed {
948-
self.unconfirmed_descendants
949-
.get_mut(&outpoint.source_id())
950-
.as_mut()
951-
.map(|descendants| descendants.insert(tx_id.clone()));
952-
} else {
953-
self.unconfirmed_descendants.remove(tx_id);
951+
if let Some(descendants) =
952+
self.unconfirmed_descendants.get_mut(&outpoint.source_id())
953+
{
954+
if is_unconfirmed {
955+
descendants.insert(tx_id.clone());
956+
} else {
957+
descendants.remove(tx_id);
958+
}
954959
}
955960
}
956961
TxInput::Account(outpoint) => match outpoint.account() {
@@ -1753,8 +1758,8 @@ fn uses_conflicting_nonce(
17531758
confirmed_account_type: AccountType,
17541759
confirmed_nonce: AccountNonce,
17551760
) -> bool {
1756-
unconfirmed_tx.inputs().iter().all(|inp| match inp {
1757-
TxInput::Utxo(_) => true,
1761+
unconfirmed_tx.inputs().iter().any(|inp| match inp {
1762+
TxInput::Utxo(_) => false,
17581763
TxInput::AccountCommand(nonce, cmd) => {
17591764
confirmed_account_type == cmd.into() && *nonce <= confirmed_nonce
17601765
}

0 commit comments

Comments
 (0)