@@ -1118,22 +1118,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
1118
1118
bool fUpdated = false ;
1119
1119
if (!fInsertedNew )
1120
1120
{
1121
- // Merge
1122
- if (!wtxIn.hashUnset () && wtxIn.hashBlock != wtx.hashBlock )
1123
- {
1124
- wtx.hashBlock = wtxIn.hashBlock ;
1125
- fUpdated = true ;
1126
- }
1127
- // If no longer abandoned, update
1128
- if (wtxIn.hashBlock .IsNull () && wtx.isAbandoned ())
1129
- {
1130
- wtx.hashBlock = wtxIn.hashBlock ;
1131
- fUpdated = true ;
1132
- }
1133
- if (wtxIn.nIndex != -1 && (wtxIn.nIndex != wtx.nIndex ))
1134
- {
1135
- wtx.nIndex = wtxIn.nIndex ;
1121
+ if (wtxIn.m_confirm .status != wtx.m_confirm .status ) {
1122
+ wtx.m_confirm .status = wtxIn.m_confirm .status ;
1123
+ wtx.m_confirm .nIndex = wtxIn.m_confirm .nIndex ;
1124
+ wtx.m_confirm .hashBlock = wtxIn.m_confirm .hashBlock ;
1136
1125
fUpdated = true ;
1126
+ } else {
1127
+ assert (wtx.m_confirm .nIndex == wtxIn.m_confirm .nIndex );
1128
+ assert (wtx.m_confirm .hashBlock == wtxIn.m_confirm .hashBlock );
1137
1129
}
1138
1130
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe )
1139
1131
{
@@ -1194,14 +1186,14 @@ void CWallet::LoadToWallet(const CWalletTx& wtxIn)
1194
1186
auto it = mapWallet.find (txin.prevout .hash );
1195
1187
if (it != mapWallet.end ()) {
1196
1188
CWalletTx& prevtx = it->second ;
1197
- if (prevtx.nIndex == - 1 && !prevtx. hashUnset ()) {
1198
- MarkConflicted (prevtx.hashBlock , wtx.GetHash ());
1189
+ if (prevtx.isConflicted ()) {
1190
+ MarkConflicted (prevtx.m_confirm . hashBlock , wtx.GetHash ());
1199
1191
}
1200
1192
}
1201
1193
}
1202
1194
}
1203
1195
1204
- bool CWallet::AddToWalletIfInvolvingMe (const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool fUpdate )
1196
+ bool CWallet::AddToWalletIfInvolvingMe (const CTransactionRef& ptx, CWalletTx::Status status, const uint256& block_hash, int posInBlock, bool fUpdate )
1205
1197
{
1206
1198
const CTransaction& tx = *ptx;
1207
1199
{
@@ -1248,9 +1240,9 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const uint256
1248
1240
1249
1241
CWalletTx wtx (this , ptx);
1250
1242
1251
- // Get merkle branch if transaction was found in a block
1252
- if (!block_hash. IsNull ())
1253
- wtx.SetMerkleBranch ( block_hash, posInBlock);
1243
+ // Block disconnection override an abandoned tx as unconfirmed
1244
+ // which means user may have to call abandontransaction again
1245
+ wtx.SetConf (status, block_hash, posInBlock);
1254
1246
1255
1247
return AddToWallet (wtx, false );
1256
1248
}
@@ -1310,7 +1302,7 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
1310
1302
if (currentconfirm == 0 && !wtx.isAbandoned ()) {
1311
1303
// If the orig tx was not in block/mempool, none of its spends can be in mempool
1312
1304
assert (!wtx.InMempool ());
1313
- wtx.nIndex = - 1 ;
1305
+ wtx.m_confirm . nIndex = 0 ;
1314
1306
wtx.setAbandoned ();
1315
1307
wtx.MarkDirty ();
1316
1308
batch.WriteTx (wtx);
@@ -1364,8 +1356,9 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
1364
1356
if (conflictconfirms < currentconfirm) {
1365
1357
// Block is 'more conflicted' than current confirm; update.
1366
1358
// Mark transaction as conflicted with this block.
1367
- wtx.nIndex = -1 ;
1368
- wtx.hashBlock = hashBlock;
1359
+ wtx.m_confirm .nIndex = 0 ;
1360
+ wtx.m_confirm .hashBlock = hashBlock;
1361
+ wtx.setConflicted ();
1369
1362
wtx.MarkDirty ();
1370
1363
batch.WriteTx (wtx);
1371
1364
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
@@ -1383,8 +1376,9 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
1383
1376
}
1384
1377
}
1385
1378
1386
- void CWallet::SyncTransaction (const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool update_tx) {
1387
- if (!AddToWalletIfInvolvingMe (ptx, block_hash, posInBlock, update_tx))
1379
+ void CWallet::SyncTransaction (const CTransactionRef& ptx, CWalletTx::Status status, const uint256& block_hash, int posInBlock, bool update_tx)
1380
+ {
1381
+ if (!AddToWalletIfInvolvingMe (ptx, status, block_hash, posInBlock, update_tx))
1388
1382
return ; // Not one of ours
1389
1383
1390
1384
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1396,7 +1390,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const uint256& block_h
1396
1390
void CWallet::TransactionAddedToMempool (const CTransactionRef& ptx) {
1397
1391
auto locked_chain = chain ().lock ();
1398
1392
LOCK (cs_wallet);
1399
- SyncTransaction (ptx, {} /* block hash */ , 0 /* position in block */ );
1393
+ SyncTransaction (ptx, CWalletTx::Status::UNCONFIRMED, {} /* block hash */ , 0 /* position in block */ );
1400
1394
1401
1395
auto it = mapWallet.find (ptx->GetHash ());
1402
1396
if (it != mapWallet.end ()) {
@@ -1425,11 +1419,11 @@ void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransaction
1425
1419
// the notification that the conflicted transaction was evicted.
1426
1420
1427
1421
for (const CTransactionRef& ptx : vtxConflicted) {
1428
- SyncTransaction (ptx, {} /* block hash */ , 0 /* position in block */ );
1422
+ SyncTransaction (ptx, CWalletTx::Status::CONFLICTED, {} /* block hash */ , 0 /* position in block */ );
1429
1423
TransactionRemovedFromMempool (ptx);
1430
1424
}
1431
1425
for (size_t i = 0 ; i < block.vtx .size (); i++) {
1432
- SyncTransaction (block.vtx [i], block_hash, i);
1426
+ SyncTransaction (block.vtx [i], CWalletTx::Status::CONFIRMED, block_hash, i);
1433
1427
TransactionRemovedFromMempool (block.vtx [i]);
1434
1428
}
1435
1429
@@ -1440,8 +1434,12 @@ void CWallet::BlockDisconnected(const CBlock& block) {
1440
1434
auto locked_chain = chain ().lock ();
1441
1435
LOCK (cs_wallet);
1442
1436
1437
+ // At block disconnection, this will change an abandoned transaction to
1438
+ // be unconfirmed, whether or not the transaction is added back to the mempool.
1439
+ // User may have to call abandontransaction again. It may be addressed in the
1440
+ // future with a stickier abandoned state or even removing abandontransaction call.
1443
1441
for (const CTransactionRef& ptx : block.vtx ) {
1444
- SyncTransaction (ptx, {} /* block hash */ , 0 /* position in block */ );
1442
+ SyncTransaction (ptx, CWalletTx::Status::UNCONFIRMED, {} /* block hash */ , 0 /* position in block */ );
1445
1443
}
1446
1444
}
1447
1445
@@ -2078,7 +2076,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
2078
2076
break ;
2079
2077
}
2080
2078
for (size_t posInBlock = 0 ; posInBlock < block.vtx .size (); ++posInBlock) {
2081
- SyncTransaction (block.vtx [posInBlock], block_hash, posInBlock, fUpdate );
2079
+ SyncTransaction (block.vtx [posInBlock], CWalletTx::Status::CONFIRMED, block_hash, posInBlock, fUpdate );
2082
2080
}
2083
2081
// scan succeeded, record block as most recent successfully scanned
2084
2082
result.last_scanned_block = block_hash;
@@ -4050,7 +4048,7 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
4050
4048
for (const auto & entry : mapWallet) {
4051
4049
// iterate over all wallet transactions...
4052
4050
const CWalletTx &wtx = entry.second ;
4053
- if (Optional<int > height = locked_chain.getBlockHeight (wtx.hashBlock )) {
4051
+ if (Optional<int > height = locked_chain.getBlockHeight (wtx.m_confirm . hashBlock )) {
4054
4052
// ... which are already in a block
4055
4053
for (const CTxOut &txout : wtx.tx ->vout ) {
4056
4054
// iterate over all their outputs
@@ -4093,9 +4091,9 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
4093
4091
unsigned int CWallet::ComputeTimeSmart (const CWalletTx& wtx) const
4094
4092
{
4095
4093
unsigned int nTimeSmart = wtx.nTimeReceived ;
4096
- if (!wtx.hashUnset ()) {
4094
+ if (!wtx.isUnconfirmed () && !wtx. isAbandoned ()) {
4097
4095
int64_t blocktime;
4098
- if (chain ().findBlock (wtx.hashBlock , nullptr /* block */ , &blocktime)) {
4096
+ if (chain ().findBlock (wtx.m_confirm . hashBlock , nullptr /* block */ , &blocktime)) {
4099
4097
int64_t latestNow = wtx.nTimeReceived ;
4100
4098
int64_t latestEntry = 0 ;
4101
4099
@@ -4123,7 +4121,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
4123
4121
4124
4122
nTimeSmart = std::max (latestEntry, std::min (blocktime, latestNow));
4125
4123
} else {
4126
- WalletLogPrintf (" %s: found %s in block %s not in index\n " , __func__, wtx.GetHash ().ToString (), wtx.hashBlock .ToString ());
4124
+ WalletLogPrintf (" %s: found %s in block %s not in index\n " , __func__, wtx.GetHash ().ToString (), wtx.m_confirm . hashBlock .ToString ());
4127
4125
}
4128
4126
}
4129
4127
return nTimeSmart;
@@ -4634,21 +4632,23 @@ CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
4634
4632
m_pre_split = false ;
4635
4633
}
4636
4634
4637
- void CWalletTx::SetMerkleBranch ( const uint256& block_hash, int posInBlock)
4635
+ void CWalletTx::SetConf (Status status, const uint256& block_hash, int posInBlock)
4638
4636
{
4637
+ // Update tx status
4638
+ m_confirm.status = status;
4639
+
4639
4640
// Update the tx's hashBlock
4640
- hashBlock = block_hash;
4641
+ m_confirm. hashBlock = block_hash;
4641
4642
4642
4643
// set the position of the transaction in the block
4643
- nIndex = posInBlock;
4644
+ m_confirm. nIndex = posInBlock;
4644
4645
}
4645
4646
4646
4647
int CWalletTx::GetDepthInMainChain (interfaces::Chain::Lock& locked_chain) const
4647
4648
{
4648
- if (hashUnset ())
4649
- return 0 ;
4649
+ if (isUnconfirmed () || isAbandoned ()) return 0 ;
4650
4650
4651
- return locked_chain.getBlockDepth (hashBlock) * (nIndex == - 1 ? -1 : 1 );
4651
+ return locked_chain.getBlockDepth (m_confirm. hashBlock ) * (isConflicted () ? -1 : 1 );
4652
4652
}
4653
4653
4654
4654
int CWalletTx::GetBlocksToMaturity (interfaces::Chain::Lock& locked_chain) const
0 commit comments