make keystore and blockmap use hashtable
This commit is contained in:
parent
f5f6bc788d
commit
4664f07b22
11 changed files with 185 additions and 111 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -121,3 +121,7 @@ contrib/devtools/split-debug.sh
|
|||
cmake-build-*/
|
||||
|
||||
compile_commands\.json
|
||||
**/compiler*\.d
|
||||
conftest.dir/
|
||||
|
||||
confdefs.h
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
/** Template base class for fixed-sized opaque blobs. */
|
||||
template<uint32_t BITS>
|
||||
CBaseBlob<BITS>::CBaseBlob()
|
||||
CBaseBlob<BITS>::CBaseBlob() : data{}
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
template<uint32_t BITS>
|
||||
|
@ -30,8 +29,7 @@ CBaseBlob<BITS>::CBaseBlob(const CBaseBlob& o)
|
|||
template<uint32_t BITS>
|
||||
CBaseBlob<BITS>& CBaseBlob<BITS>::operator=(const CBaseBlob& o)
|
||||
{
|
||||
if (this != &o)
|
||||
std::copy(o.begin(), o.end(), begin());
|
||||
data = o.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -44,19 +42,19 @@ int CBaseBlob<BITS>::Compare(const CBaseBlob& b) const
|
|||
template<uint32_t BITS>
|
||||
bool CBaseBlob<BITS>::operator<(const CBaseBlob& b) const
|
||||
{
|
||||
return Compare(b) < 0;
|
||||
return data < b.data;
|
||||
}
|
||||
|
||||
template<uint32_t BITS>
|
||||
bool CBaseBlob<BITS>::operator==(const CBaseBlob& b) const
|
||||
{
|
||||
return Compare(b) == 0;
|
||||
return data == b.data;
|
||||
}
|
||||
|
||||
template<uint32_t BITS>
|
||||
bool CBaseBlob<BITS>::operator!=(const CBaseBlob& b) const
|
||||
{
|
||||
return !(*this == b);
|
||||
return data != b.data;
|
||||
}
|
||||
|
||||
template<uint32_t BITS>
|
||||
|
|
|
@ -40,4 +40,26 @@ uint160 uint160S(const std::string& s);
|
|||
uint256 uint256S(const char* str);
|
||||
uint256 uint256S(const std::string& s);
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<uint160>
|
||||
{
|
||||
std::size_t operator()(const uint160& k) const
|
||||
{
|
||||
return *reinterpret_cast<const std::size_t*>(k.begin());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<uint256>
|
||||
{
|
||||
std::size_t operator()(const uint256& k) const
|
||||
{
|
||||
return *reinterpret_cast<const std::size_t*>(k.begin());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // CLAIMTRIE_UINTS_H
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
|
||||
/** A virtual base class for key stores */
|
||||
class CKeyStore : public SigningProvider
|
||||
{
|
||||
|
@ -44,9 +47,9 @@ class CBasicKeyStore : public CKeyStore
|
|||
protected:
|
||||
mutable CCriticalSection cs_KeyStore;
|
||||
|
||||
using KeyMap = std::map<CKeyID, CKey>;
|
||||
using WatchKeyMap = std::map<CKeyID, CPubKey>;
|
||||
using ScriptMap = std::map<CScriptID, CScript>;
|
||||
using KeyMap = std::unordered_map<CKeyID, CKey>;
|
||||
using WatchKeyMap = std::unordered_map<CKeyID, CPubKey>;
|
||||
using ScriptMap = std::unordered_map<CScriptID, CScript>;
|
||||
using WatchOnlySet = std::set<CScript>;
|
||||
|
||||
KeyMap mapKeys GUARDED_BY(cs_KeyStore);
|
||||
|
|
11
src/pubkey.h
11
src/pubkey.h
|
@ -36,6 +36,17 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<CKeyID>
|
||||
{
|
||||
std::size_t operator()(const CKeyID& k) const
|
||||
{
|
||||
return *reinterpret_cast<const std::size_t*>(k.begin());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
typedef uint256 ChainCode;
|
||||
|
||||
/** An encapsulated public key. */
|
||||
|
|
|
@ -27,6 +27,17 @@ public:
|
|||
CScriptID(const uint160& in) : uint160(in) {}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<CScriptID>
|
||||
{
|
||||
std::size_t operator()(const CScriptID& k) const
|
||||
{
|
||||
return *reinterpret_cast<const std::size_t*>(k.begin());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Default setting for nMaxDatacarrierBytes. 80 bytes of data, +1 for OP_RETURN,
|
||||
* +2 for the pushdata opcodes.
|
||||
|
|
|
@ -145,21 +145,27 @@ extern CBlockPolicyEstimator feeEstimator;
|
|||
extern CTxMemPool mempool;
|
||||
extern std::atomic_bool g_is_mempool_loaded;
|
||||
|
||||
struct BlockIndexPointerCompare {
|
||||
inline bool operator() (const CBlockIndex* lhs, const CBlockIndex* rhs) const {
|
||||
return lhs->hash < rhs->hash;
|
||||
struct BlockMapHasher {
|
||||
std::size_t operator()(const CBlockIndex* block) const {
|
||||
return *reinterpret_cast<const std::size_t*>(block->hash.begin());
|
||||
}
|
||||
};
|
||||
|
||||
struct BlockMap : public std::set<CBlockIndex*, BlockIndexPointerCompare> {
|
||||
struct BlockMapComparer {
|
||||
bool operator()(const CBlockIndex* a, const CBlockIndex* b) const {
|
||||
return a == b || a->hash == b->hash;
|
||||
}
|
||||
};
|
||||
|
||||
struct BlockMap : public std::unordered_set<CBlockIndex*, BlockMapHasher, BlockMapComparer> {
|
||||
inline iterator find(const uint256& blockHash) {
|
||||
CBlockIndex temp(blockHash);
|
||||
return std::set<CBlockIndex*, BlockIndexPointerCompare>::find(&temp);
|
||||
return std::unordered_set<CBlockIndex*, BlockMapHasher, BlockMapComparer>::find(&temp);
|
||||
}
|
||||
|
||||
inline const_iterator find(const uint256& blockHash) const {
|
||||
CBlockIndex temp(blockHash);
|
||||
return std::set<CBlockIndex*, BlockIndexPointerCompare>::find(&temp);
|
||||
return std::unordered_set<CBlockIndex*, BlockMapHasher, BlockMapComparer>::find(&temp);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ private:
|
|||
bool fDecryptionThoroughlyChecked;
|
||||
|
||||
protected:
|
||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
using CryptedKeyMap = std::unordered_map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
|
||||
bool SetCrypted();
|
||||
|
||||
|
|
|
@ -467,15 +467,11 @@ static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
|
|||
static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue,
|
||||
bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue, std::string fromAccount,
|
||||
const CScript& prefix = CScript()){
|
||||
CAmount curBalance = pwallet->GetBalance();
|
||||
|
||||
// Check amount
|
||||
if (nValue <= 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
|
||||
|
||||
if (nValue > curBalance)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
|
||||
|
||||
if (pwallet->GetBroadcastTransactions() && !g_connman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
@ -493,6 +489,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
|
|||
vecSend.push_back(recipient);
|
||||
CTransactionRef tx;
|
||||
if (!pwallet->CreateTransaction(vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
|
||||
CAmount curBalance = pwallet->GetBalance();
|
||||
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
|
||||
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||
|
@ -2193,7 +2190,6 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
|
|||
for (auto item_it = start; item_it != end; ++item_it)
|
||||
{
|
||||
const CTxDestination& address = item_it->first;
|
||||
const std::string& label = item_it->second.name;
|
||||
auto it = mapTally.find(address);
|
||||
if (it == mapTally.end() && !fIncludeEmpty)
|
||||
continue;
|
||||
|
@ -2208,6 +2204,7 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
|
|||
fIsWatchonly = (*it).second.fIsWatchonly;
|
||||
}
|
||||
|
||||
const std::string& label = item_it->second.name;
|
||||
if (by_label)
|
||||
{
|
||||
tallyitem& _item = label_tally[label];
|
||||
|
@ -2225,6 +2222,7 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
|
|||
obj.pushKV("amount", ValueFromAmount(nAmount));
|
||||
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
|
||||
obj.pushKV("label", label);
|
||||
obj.pushKV("purpose", item_it->second.purpose);
|
||||
UniValue transactions(UniValue::VARR);
|
||||
if (it != mapTally.end())
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <wallet/fees.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <future>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
@ -54,7 +54,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
|
|||
{
|
||||
LOCK(cs_wallets);
|
||||
assert(wallet);
|
||||
std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
|
||||
auto i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
|
||||
if (i == vpwallets.end()) return false;
|
||||
vpwallets.erase(i);
|
||||
return true;
|
||||
|
@ -208,7 +208,7 @@ public:
|
|||
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
|
||||
auto it = mapWallet.find(hash);
|
||||
if (it == mapWallet.end())
|
||||
return nullptr;
|
||||
return &(it->second);
|
||||
|
@ -560,7 +560,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
|
|||
std::set<uint256> result;
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
|
||||
auto it = mapWallet.find(txid);
|
||||
if (it == mapWallet.end())
|
||||
return result;
|
||||
const CWalletTx& wtx = it->second;
|
||||
|
@ -569,11 +569,16 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
|
|||
|
||||
for (const CTxIn& txin : wtx.tx->vin)
|
||||
{
|
||||
if (mapTxSpends.count(txin.prevout) <= 1)
|
||||
auto hitTx = mapTxSpends.find(txin.prevout.hash);
|
||||
if (hitTx == mapTxSpends.end())
|
||||
continue;
|
||||
auto hitN = hitTx->second.find(txin.prevout.n);
|
||||
if (hitN == hitTx->second.end())
|
||||
continue;
|
||||
if (hitN->second.size() <= 1U)
|
||||
continue; // No conflict if zero or one spends
|
||||
range = mapTxSpends.equal_range(txin.prevout);
|
||||
for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
|
||||
result.insert(_it->second);
|
||||
for (auto& spend: hitN->second)
|
||||
result.insert(spend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -581,8 +586,14 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
|
|||
bool CWallet::HasWalletSpend(const uint256& txid) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
|
||||
return (iter != mapTxSpends.end() && iter->first.hash == txid);
|
||||
auto hitTx = mapTxSpends.find(txid);
|
||||
if (hitTx == mapTxSpends.end())
|
||||
return false;
|
||||
for (auto& kvp: hitTx->second) {
|
||||
if (!kvp.second.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWallet::Flush(bool shutdown)
|
||||
|
@ -590,7 +601,7 @@ void CWallet::Flush(bool shutdown)
|
|||
database->Flush(shutdown);
|
||||
}
|
||||
|
||||
void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
|
||||
void CWallet::SyncMetaData(const COutPoint& outPoint)
|
||||
{
|
||||
// We want all the wallet transactions in range to have the same metadata as
|
||||
// the oldest (smallest nOrderPos).
|
||||
|
@ -598,22 +609,24 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
|
|||
|
||||
int nMinOrderPos = std::numeric_limits<int>::max();
|
||||
const CWalletTx* copyFrom = nullptr;
|
||||
for (TxSpends::iterator it = range.first; it != range.second; ++it) {
|
||||
const CWalletTx* wtx = &mapWallet.at(it->second);
|
||||
|
||||
auto hitTx = mapTxSpends.find(outPoint.hash);
|
||||
if (hitTx != mapTxSpends.end()) {
|
||||
auto hitN = hitTx->second.find(outPoint.n);
|
||||
if (hitN != hitTx->second.end()) {
|
||||
for (auto &spend: hitN->second) {
|
||||
const CWalletTx *wtx = &mapWallet.at(spend);
|
||||
if (wtx->nOrderPos < nMinOrderPos) {
|
||||
nMinOrderPos = wtx->nOrderPos;
|
||||
copyFrom = wtx;
|
||||
}
|
||||
}
|
||||
|
||||
if (!copyFrom) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now copy data from copyFrom to rest:
|
||||
for (TxSpends::iterator it = range.first; it != range.second; ++it)
|
||||
{
|
||||
const uint256& hash = it->second;
|
||||
for (auto &hash: hitN->second) {
|
||||
CWalletTx *copyTo = &mapWallet.at(hash);
|
||||
if (copyFrom == copyTo) continue;
|
||||
assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
|
||||
|
@ -629,6 +642,8 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
|
|||
// cached members not copied on purpose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outpoint is spent if any non-conflicted transaction
|
||||
|
@ -636,14 +651,15 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
|
|||
*/
|
||||
bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
|
||||
{
|
||||
const COutPoint outpoint(hash, n);
|
||||
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
|
||||
range = mapTxSpends.equal_range(outpoint);
|
||||
auto hitTx = mapTxSpends.find(hash);
|
||||
if (hitTx == mapTxSpends.end())
|
||||
return false;
|
||||
auto hitN = hitTx->second.find(n);
|
||||
if (hitN == hitTx->second.end())
|
||||
return false;
|
||||
|
||||
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
|
||||
{
|
||||
const uint256& wtxid = it->second;
|
||||
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
|
||||
for (auto& wtxid: hitN->second) {
|
||||
auto mit = mapWallet.find(wtxid);
|
||||
if (mit != mapWallet.end()) {
|
||||
int depth = mit->second.GetDepthInMainChain();
|
||||
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
|
||||
|
@ -655,13 +671,9 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
|
|||
|
||||
void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
|
||||
{
|
||||
mapTxSpends.insert(std::make_pair(outpoint, wtxid));
|
||||
|
||||
mapTxSpends[outpoint.hash][outpoint.n].push_back(wtxid);
|
||||
setLockedCoins.erase(outpoint);
|
||||
|
||||
std::pair<TxSpends::iterator, TxSpends::iterator> range;
|
||||
range = mapTxSpends.equal_range(outpoint);
|
||||
SyncMetaData(range);
|
||||
SyncMetaData(outpoint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -907,9 +919,7 @@ bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label
|
|||
else {
|
||||
// Check if the current key has been used (TODO: check other addresses with the same key)
|
||||
CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, m_default_address_type));
|
||||
for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin();
|
||||
it != mapWallet.end() && account.vchPubKey.IsValid();
|
||||
++it)
|
||||
for (auto it = mapWallet.begin(); it != mapWallet.end() && account.vchPubKey.IsValid(); ++it)
|
||||
for (const CTxOut& txout : (*it).second.tx->vout)
|
||||
if (txout.scriptPubKey == scriptPubKey) {
|
||||
bForceNew = true;
|
||||
|
@ -981,7 +991,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
|||
uint256 hash = wtxIn.GetHash();
|
||||
|
||||
// Inserts only if not already there, returns tx inserted or tx found
|
||||
std::pair<std::map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(std::make_pair(hash, wtxIn));
|
||||
auto ret = mapWallet.insert(std::make_pair(hash, wtxIn));
|
||||
CWalletTx& wtx = (*ret.first).second;
|
||||
wtx.BindWallet(this);
|
||||
bool fInsertedNew = ret.second;
|
||||
|
@ -1086,13 +1096,19 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
|
|||
|
||||
if (pIndex != nullptr) {
|
||||
for (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()) {
|
||||
WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
|
||||
MarkConflicted(pIndex->GetBlockHash(), range.first->second);
|
||||
auto hitTx = mapTxSpends.find(txin.prevout.hash);
|
||||
if (hitTx == mapTxSpends.end())
|
||||
continue;
|
||||
auto hitN = hitTx->second.find(txin.prevout.n);
|
||||
if (hitN == hitTx->second.end())
|
||||
continue;
|
||||
|
||||
for (auto& spend: hitN->second) {
|
||||
if (spend != tx.GetHash()) {
|
||||
WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n",
|
||||
tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), spend.ToString(), hitTx->first.ToString(), hitN->first);
|
||||
MarkConflicted(pIndex->GetBlockHash(), spend);
|
||||
}
|
||||
range.first++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1113,7 +1129,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
|
|||
std::vector<CKeyID> vAffected;
|
||||
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
|
||||
for (const CKeyID &keyid : vAffected) {
|
||||
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
|
||||
auto mi = m_pool_key_to_index.find(keyid);
|
||||
if (mi != m_pool_key_to_index.end()) {
|
||||
WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
|
||||
MarkReserveKeysAsUsed(mi->second);
|
||||
|
@ -1177,7 +1193,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
|
|||
uint256 now = *todo.begin();
|
||||
todo.erase(now);
|
||||
done.insert(now);
|
||||
auto it = mapWallet.find(now);
|
||||
it = mapWallet.find(now);
|
||||
assert(it != mapWallet.end());
|
||||
CWalletTx& wtx = it->second;
|
||||
int currentconfirm = wtx.GetDepthInMainChain();
|
||||
|
@ -1193,12 +1209,14 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
|
|||
batch.WriteTx(wtx);
|
||||
NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED);
|
||||
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned 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.insert(iter->second);
|
||||
auto hitTx = mapTxSpends.find(now);
|
||||
if (hitTx != mapTxSpends.end()) {
|
||||
for (auto &kvp: hitTx->second) {
|
||||
for (auto &spent: kvp.second) {
|
||||
if (!done.count(spent))
|
||||
todo.insert(spent);
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
// If a transaction changes 'conflicted' state, that changes the balance
|
||||
// available of the outputs it spends. So force those to be recomputed
|
||||
|
@ -1249,12 +1267,14 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
|
|||
wtx.MarkDirty();
|
||||
batch.WriteTx(wtx);
|
||||
// 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.insert(iter->second);
|
||||
auto hitTx = mapTxSpends.find(now);
|
||||
if (hitTx != mapTxSpends.end()) {
|
||||
for (auto &kvp: hitTx->second) {
|
||||
for (auto &spent: kvp.second) {
|
||||
if (!done.count(spent))
|
||||
todo.insert(spent);
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
// If a transaction changes 'conflicted' state, that changes the balance
|
||||
// available of the outputs it spends. So force those to be recomputed
|
||||
|
@ -1352,7 +1372,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const
|
|||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
auto mi = mapWallet.find(txin.prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
|
@ -1369,7 +1389,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
|||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
|
||||
auto mi = mapWallet.find(txin.prevout.hash);
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
|
@ -2388,7 +2408,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
|
|||
solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey); // this is a slow call
|
||||
spendable = solvable;
|
||||
computedSolvable = true;
|
||||
};
|
||||
}
|
||||
if (computeSolvable && !computedSolvable)
|
||||
solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
|
||||
|
||||
|
@ -2560,7 +2580,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
|
|||
bnb_used = false;
|
||||
coin_selection_params.use_bnb = false;
|
||||
|
||||
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
|
||||
auto it = mapWallet.find(outpoint.hash);
|
||||
if (it != mapWallet.end())
|
||||
{
|
||||
const CWalletTx* pcoin = &it->second;
|
||||
|
@ -2622,7 +2642,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
|
|||
// sign the new tx
|
||||
int nIn = 0;
|
||||
for (auto& input : tx.vin) {
|
||||
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
|
||||
auto mi = mapWallet.find(input.prevout.hash);
|
||||
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3886,7 +3906,7 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
|
|||
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
|
||||
for (const CKeyID &keyid : vAffected) {
|
||||
// ... and all their affected keys
|
||||
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
|
||||
auto rit = mapKeyFirstBlock.find(keyid);
|
||||
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
|
||||
rit->second = pindex;
|
||||
}
|
||||
|
@ -4381,7 +4401,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const WalletLocation& loc
|
|||
for (const CWalletTx& wtxOld : vWtx)
|
||||
{
|
||||
uint256 hash = wtxOld.GetHash();
|
||||
std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
|
||||
auto mi = walletInstance->mapWallet.find(hash);
|
||||
if (mi != walletInstance->mapWallet.end())
|
||||
{
|
||||
const CWalletTx* copyFrom = &wtxOld;
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -699,7 +699,7 @@ private:
|
|||
* detect and report conflicts (double-spends or
|
||||
* mutated transactions where the mutant gets mined).
|
||||
*/
|
||||
typedef std::multimap<COutPoint, uint256> TxSpends;
|
||||
typedef std::unordered_map<uint256, std::unordered_map<uint32_t, std::vector<uint256>>> TxSpends;
|
||||
TxSpends mapTxSpends;
|
||||
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
|
||||
void AddToSpends(const uint256& wtxid);
|
||||
|
@ -725,7 +725,7 @@ private:
|
|||
/* Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed */
|
||||
void MarkInputsDirty(const CTransactionRef& tx);
|
||||
|
||||
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
|
||||
void SyncMetaData(const COutPoint& outpoint);
|
||||
|
||||
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
|
||||
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
|
||||
|
@ -808,17 +808,18 @@ public:
|
|||
void MarkPreSplitKeys();
|
||||
|
||||
// Map from Key ID to key metadata.
|
||||
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
|
||||
std::unordered_map<CKeyID, CKeyMetadata> mapKeyMetadata;
|
||||
|
||||
// Map from Script ID to key metadata (for watch-only keys).
|
||||
std::map<CScriptID, CKeyMetadata> m_script_metadata;
|
||||
std::unordered_map<CScriptID, CKeyMetadata> m_script_metadata;
|
||||
|
||||
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
||||
MasterKeyMap mapMasterKeys;
|
||||
unsigned int nMasterKeyMaxID = 0;
|
||||
|
||||
/** Construct wallet with specified name and database implementation. */
|
||||
CWallet(const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_location(location), database(std::move(database))
|
||||
CWallet(const WalletLocation& location, std::unique_ptr<WalletDatabase> database)
|
||||
: m_location(location), database(std::move(database))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -830,7 +831,7 @@ public:
|
|||
encrypted_batch = nullptr;
|
||||
}
|
||||
|
||||
std::map<uint256, CWalletTx> mapWallet;
|
||||
std::unordered_map<uint256, CWalletTx> mapWallet;
|
||||
std::list<CAccountingEntry> laccentries;
|
||||
|
||||
typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
|
||||
|
|
Loading…
Reference in a new issue