Keep track of spent notes, and detect and report conflicts

This commit is contained in:
Jack Grigg
2016-08-24 15:51:40 +12:00
parent c3a7307a69
commit 0f1060478f
3 changed files with 188 additions and 7 deletions

View File

@@ -401,6 +401,20 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
result.insert(it->second);
}
std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
for (const JSDescription& jsdesc : wtx.vjoinsplit) {
for (const uint256& nullifier : jsdesc.nullifiers) {
if (mapTxNullifiers.count(nullifier) <= 1) {
continue; // No conflict if zero or one spends
}
range_n = mapTxNullifiers.equal_range(nullifier);
for (TxNullifiers::const_iterator it = range_n.first; it != range_n.second; ++it) {
result.insert(it->second);
}
}
}
return result;
}
@@ -456,7 +470,8 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
return true;
}
void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
template <class T>
void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
{
// We want all the wallet transactions in range to have the same metadata as
// the oldest (smallest nOrderPos).
@@ -464,7 +479,7 @@ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
int nMinOrderPos = std::numeric_limits<int>::max();
const CWalletTx* copyFrom = NULL;
for (TxSpends::iterator it = range.first; it != range.second; ++it)
for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
{
const uint256& hash = it->second;
int n = mapWallet[hash].nOrderPos;
@@ -475,7 +490,7 @@ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
}
}
// Now copy data from copyFrom to rest:
for (TxSpends::iterator it = range.first; it != range.second; ++it)
for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
{
const uint256& hash = it->second;
CWalletTx* copyTo = &mapWallet[hash];
@@ -514,15 +529,42 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
return false;
}
/**
* Note is spent if any non-conflicted transaction
* spends it:
*/
bool CWallet::IsSpent(const uint256& nullifier) const
{
pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
range = mapTxNullifiers.equal_range(nullifier);
for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
return true; // Spent
}
}
return false;
}
void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
{
mapTxSpends.insert(make_pair(outpoint, wtxid));
pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
SyncMetaData(range);
SyncMetaData<COutPoint>(range);
}
void CWallet::AddToSpends(const uint256& nullifier, const uint256& wtxid)
{
mapTxNullifiers.insert(make_pair(nullifier, wtxid));
pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
range = mapTxNullifiers.equal_range(nullifier);
SyncMetaData<uint256>(range);
}
void CWallet::AddToSpends(const uint256& wtxid)
{
@@ -531,8 +573,14 @@ void CWallet::AddToSpends(const uint256& wtxid)
if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
return;
BOOST_FOREACH(const CTxIn& txin, thisTx.vin)
for (const CTxIn& txin : thisTx.vin) {
AddToSpends(txin.prevout, wtxid);
}
for (const JSDescription& jsdesc : thisTx.vjoinsplit) {
for (const uint256& nullifier : jsdesc.nullifiers) {
AddToSpends(nullifier, wtxid);
}
}
}
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)