@ -608,6 +608,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
@@ -608,6 +608,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
wtx . BindWallet ( this ) ;
wtxOrdered . insert ( make_pair ( wtx . nOrderPos , TxPair ( & wtx , ( CAccountingEntry * ) 0 ) ) ) ;
AddToSpends ( hash ) ;
BOOST_FOREACH ( const CTxIn & txin , wtx . vin ) {
if ( mapWallet . count ( txin . prevout . hash ) ) {
CWalletTx & prevtx = mapWallet [ txin . prevout . hash ] ;
if ( prevtx . nIndex = = - 1 & & ! prevtx . hashBlock . IsNull ( ) ) {
MarkConflicted ( prevtx . hashBlock , wtx . GetHash ( ) ) ;
}
}
}
}
else
{
@ -727,6 +735,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
@@ -727,6 +735,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
{
{
AssertLockHeld ( cs_wallet ) ;
if ( pblock ) {
BOOST_FOREACH ( const CTxIn & txin , tx . vin ) {
std : : pair < TxSpends : : const_iterator , TxSpends : : const_iterator > range = mapTxSpends . equal_range ( txin . prevout ) ;
while ( range . first ! = range . second ) {
if ( range . first - > second ! = tx . GetHash ( ) ) {
LogPrintf ( " Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i) \n " , tx . GetHash ( ) . ToString ( ) , pblock - > GetHash ( ) . ToString ( ) , range . first - > second . ToString ( ) , range . first - > first . hash . ToString ( ) , range . first - > first . n ) ;
MarkConflicted ( pblock - > GetHash ( ) , range . first - > second ) ;
}
range . first + + ;
}
}
}
bool fExisted = mapWallet . count ( tx . GetHash ( ) ) ! = 0 ;
if ( fExisted & & ! fUpdate ) return false ;
if ( fExisted | | IsMine ( tx ) | | IsFromMe ( tx ) )
@ -747,9 +769,57 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
@@ -747,9 +769,57 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
return false ;
}
void CWallet : : MarkConflicted ( const uint256 & hashBlock , const uint256 & hashTx )
{
LOCK2 ( cs_main , cs_wallet ) ;
CBlockIndex * pindex ;
assert ( mapBlockIndex . count ( hashBlock ) ) ;
pindex = mapBlockIndex [ hashBlock ] ;
int conflictconfirms = 0 ;
if ( chainActive . Contains ( pindex ) ) {
conflictconfirms = - ( chainActive . Height ( ) - pindex - > nHeight + 1 ) ;
}
assert ( conflictconfirms < 0 ) ;
// Do not flush the wallet here for performance reasons
CWalletDB walletdb ( strWalletFile , " r+ " , false ) ;
std : : deque < uint256 > todo ;
std : : set < uint256 > done ;
todo . push_back ( hashTx ) ;
while ( ! todo . empty ( ) ) {
uint256 now = todo . front ( ) ;
todo . pop_front ( ) ;
done . insert ( now ) ;
assert ( mapWallet . count ( now ) ) ;
CWalletTx & wtx = mapWallet [ now ] ;
int currentconfirm = wtx . GetDepthInMainChain ( ) ;
if ( conflictconfirms < currentconfirm ) {
// Block is 'more conflicted' than current confirm; update.
// Mark transaction as conflicted with this block.
wtx . nIndex = - 1 ;
wtx . hashBlock = hashBlock ;
wtx . MarkDirty ( ) ;
wtx . WriteToDisk ( & walletdb ) ;
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
TxSpends : : const_iterator iter = mapTxSpends . lower_bound ( COutPoint ( now , 0 ) ) ;
while ( iter ! = mapTxSpends . end ( ) & & iter - > first . hash = = now ) {
if ( ! done . count ( iter - > second ) ) {
todo . push_back ( iter - > second ) ;
}
iter + + ;
}
}
}
}
void CWallet : : SyncTransaction ( const CTransaction & tx , const CBlock * pblock )
{
LOCK2 ( cs_main , cs_wallet ) ;
if ( ! AddToWalletIfInvolvingMe ( tx , pblock , true ) )
return ; // Not one of ours
@ -1089,7 +1159,7 @@ void CWallet::ReacceptWalletTransactions()
@@ -1089,7 +1159,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx . GetDepthInMainChain ( ) ;
if ( ! wtx . IsCoinBase ( ) & & nDepth < 0 ) {
if ( ! wtx . IsCoinBase ( ) & & nDepth = = 0 ) {
mapSorted . insert ( std : : make_pair ( wtx . nOrderPos , & wtx ) ) ;
}
}
@ -1303,6 +1373,14 @@ bool CWalletTx::IsTrusted() const
@@ -1303,6 +1373,14 @@ bool CWalletTx::IsTrusted() const
if ( ! bSpendZeroConfChange | | ! IsFromMe ( ISMINE_ALL ) ) // using wtx's cached debit
return false ;
// Don't trust unconfirmed transactions from us unless they are in the mempool.
{
LOCK ( mempool . cs ) ;
if ( ! mempool . exists ( GetHash ( ) ) ) {
return false ;
}
}
// Trusted if all inputs are from us and are in the mempool:
BOOST_FOREACH ( const CTxIn & txin , vin )
{
@ -1879,6 +1957,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
@@ -1879,6 +1957,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
//a chance at a free transaction.
//But mempool inputs might still be in the mempool, so their age stays 0
int age = pcoin . first - > GetDepthInMainChain ( ) ;
assert ( age > = 0 ) ;
if ( age ! = 0 )
age + = 1 ;
dPriority + = ( double ) nCredit * age ;
@ -2814,9 +2893,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
@@ -2814,9 +2893,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
return chainActive . Height ( ) - pindex - > nHeight + 1 ;
}
int CMerkleTx : : GetDepthInMainChainINTERNAL ( const CBlockIndex * & pindexRet ) const
int CMerkleTx : : GetDepthInMainChain ( const CBlockIndex * & pindexRet ) const
{
if ( hashBlock . IsNull ( ) | | nIndex = = - 1 )
if ( hashBlock . IsNull ( ) )
return 0 ;
AssertLockHeld ( cs_main ) ;
@ -2829,17 +2908,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
@@ -2829,17 +2908,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
return 0 ;
pindexRet = pindex ;
return chainActive . Height ( ) - pindex - > nHeight + 1 ;
}
int CMerkleTx : : GetDepthInMainChain ( const CBlockIndex * & pindexRet ) const
{
AssertLockHeld ( cs_main ) ;
int nResult = GetDepthInMainChainINTERNAL ( pindexRet ) ;
if ( nResult = = 0 & & ! mempool . exists ( GetHash ( ) ) )
return - 1 ; // Not in chain, not in mempool
return nResult ;
return ( ( nIndex = = - 1 ) ? ( - 1 ) : 1 ) * ( chainActive . Height ( ) - pindex - > nHeight + 1 ) ;
}
int CMerkleTx : : GetBlocksToMaturity ( ) const