Skip to content

Commit 2e96176

Browse files
committed
wallet: don't include unconfirmed v3 txs with children in available coins
1 parent ec2676b commit 2e96176

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

src/wallet/spend.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,11 @@ CoinsResult AvailableCoins(const CWallet& wallet,
390390
if (nDepth == 0 && params.check_version_trucness) {
391391
if (coinControl->m_version == TRUC_VERSION) {
392392
if (wtx.tx->version != TRUC_VERSION) continue;
393+
// this unconfirmed v3 transaction already has a child
394+
if (wtx.truc_child_in_mempool.has_value()) continue;
393395
} else {
394396
if (wtx.tx->version == TRUC_VERSION) continue;
397+
Assume(!wtx.truc_child_in_mempool.has_value());
395398
}
396399
}
397400

src/wallet/transaction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ class CWalletTx
258258
// BlockConflicted.
259259
std::set<Txid> mempool_conflicts;
260260

261+
// Track v3 mempool tx that spends from this tx
262+
// so that we don't try to create another unconfirmed child
263+
std::optional<Txid> truc_child_in_mempool;
264+
261265
template<typename Stream>
262266
void Serialize(Stream& s) const
263267
{

src/wallet/wallet.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <node/types.h>
3131
#include <outputtype.h>
3232
#include <policy/feerate.h>
33+
#include <policy/truc_policy.h>
3334
#include <primitives/block.h>
3435
#include <primitives/transaction.h>
3536
#include <psbt.h>
@@ -1388,6 +1389,22 @@ void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
13881389
return wtx.mempool_conflicts.insert(txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
13891390
});
13901391
}
1392+
1393+
}
1394+
1395+
if (tx->version == TRUC_VERSION) {
1396+
// Unconfirmed TRUC transactions are only allowed a 1-parent-1-child topology.
1397+
// For any unconfirmed v3 parents (there should be a maximum of 1 except in reorgs),
1398+
// record this child so the wallet doesn't try to spend any other outputs
1399+
for (const CTxIn& tx_in : tx->vin) {
1400+
auto parent_it = mapWallet.find(tx_in.prevout.hash);
1401+
if (parent_it != mapWallet.end()) {
1402+
CWalletTx& parent_wtx = parent_it->second;
1403+
if (parent_wtx.isUnconfirmed()) {
1404+
parent_wtx.truc_child_in_mempool = tx->GetHash();
1405+
}
1406+
}
1407+
}
13911408
}
13921409
}
13931410

@@ -1441,6 +1458,22 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
14411458
});
14421459
}
14431460
}
1461+
1462+
if (tx->version == TRUC_VERSION) {
1463+
// If this tx has a parent, unset its truc_child_in_mempool to make it possible
1464+
// to spend from the parent again. If this tx was replaced by another
1465+
// child of the same parent, transactionAddedToMempool
1466+
// will update truc_child_in_mempool
1467+
for (const CTxIn& tx_in : tx->vin) {
1468+
auto parent_it = mapWallet.find(tx_in.prevout.hash);
1469+
if (parent_it != mapWallet.end()) {
1470+
CWalletTx& parent_wtx = parent_it->second;
1471+
if (parent_wtx.truc_child_in_mempool == tx->GetHash()) {
1472+
parent_wtx.truc_child_in_mempool = std::nullopt;
1473+
}
1474+
}
1475+
}
1476+
}
14441477
}
14451478

14461479
void CWallet::blockConnected(ChainstateRole role, const interfaces::BlockInfo& block)

0 commit comments

Comments
 (0)