Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 875 Lines • ▼ Show 20 Lines | DBErrors CWallet::ReorderTransactions() { | ||||
// bad idea to change the output of this. | // bad idea to change the output of this. | ||||
// First: get all CWalletTx into a sorted-by-time | // First: get all CWalletTx into a sorted-by-time | ||||
// multimap. | // multimap. | ||||
TxItems txByTime; | TxItems txByTime; | ||||
for (auto &entry : mapWallet) { | for (auto &entry : mapWallet) { | ||||
CWalletTx *wtx = &entry.second; | CWalletTx *wtx = &entry.second; | ||||
txByTime.insert( | txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx)); | ||||
std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr))); | |||||
} | } | ||||
nOrderPosNext = 0; | nOrderPosNext = 0; | ||||
std::vector<int64_t> nOrderPosOffsets; | std::vector<int64_t> nOrderPosOffsets; | ||||
for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) { | for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) { | ||||
CWalletTx *const pwtx = (*it).second.first; | CWalletTx *const pwtx = (*it).second; | ||||
CAccountingEntry *const pacentry = (*it).second.second; | int64_t &nOrderPos = pwtx->nOrderPos; | ||||
int64_t &nOrderPos = | |||||
(pwtx != nullptr) ? pwtx->nOrderPos : pacentry->nOrderPos; | |||||
if (nOrderPos == -1) { | if (nOrderPos == -1) { | ||||
nOrderPos = nOrderPosNext++; | nOrderPos = nOrderPosNext++; | ||||
nOrderPosOffsets.push_back(nOrderPos); | nOrderPosOffsets.push_back(nOrderPos); | ||||
if (pwtx) { | |||||
if (!batch.WriteTx(*pwtx)) { | if (!batch.WriteTx(*pwtx)) { | ||||
return DBErrors::LOAD_FAIL; | return DBErrors::LOAD_FAIL; | ||||
} | } | ||||
} | |||||
} else { | } else { | ||||
int64_t nOrderPosOff = 0; | int64_t nOrderPosOff = 0; | ||||
for (const int64_t &nOffsetStart : nOrderPosOffsets) { | for (const int64_t &nOffsetStart : nOrderPosOffsets) { | ||||
if (nOrderPos >= nOffsetStart) { | if (nOrderPos >= nOffsetStart) { | ||||
++nOrderPosOff; | ++nOrderPosOff; | ||||
} | } | ||||
} | } | ||||
nOrderPos += nOrderPosOff; | nOrderPos += nOrderPosOff; | ||||
nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1); | nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1); | ||||
if (!nOrderPosOff) { | if (!nOrderPosOff) { | ||||
continue; | continue; | ||||
} | } | ||||
// Since we're changing the order, write it back. | // Since we're changing the order, write it back. | ||||
if (pwtx) { | |||||
if (!batch.WriteTx(*pwtx)) { | if (!batch.WriteTx(*pwtx)) { | ||||
return DBErrors::LOAD_FAIL; | return DBErrors::LOAD_FAIL; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | |||||
batch.WriteOrderPosNext(nOrderPosNext); | batch.WriteOrderPosNext(nOrderPosNext); | ||||
return DBErrors::LOAD_OK; | return DBErrors::LOAD_OK; | ||||
} | } | ||||
int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { | int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { | ||||
// nOrderPosNext | // nOrderPosNext | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | bool CWallet::AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose) { | ||||
std::pair<std::map<TxId, CWalletTx>::iterator, bool> ret = | std::pair<std::map<TxId, CWalletTx>::iterator, bool> ret = | ||||
mapWallet.insert(std::make_pair(txid, wtxIn)); | mapWallet.insert(std::make_pair(txid, wtxIn)); | ||||
CWalletTx &wtx = (*ret.first).second; | CWalletTx &wtx = (*ret.first).second; | ||||
wtx.BindWallet(this); | wtx.BindWallet(this); | ||||
bool fInsertedNew = ret.second; | bool fInsertedNew = ret.second; | ||||
if (fInsertedNew) { | if (fInsertedNew) { | ||||
wtx.nTimeReceived = GetAdjustedTime(); | wtx.nTimeReceived = GetAdjustedTime(); | ||||
wtx.nOrderPos = IncOrderPosNext(&batch); | wtx.nOrderPos = IncOrderPosNext(&batch); | ||||
wtx.m_it_wtxOrdered = wtxOrdered.insert( | wtx.m_it_wtxOrdered = | ||||
std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); | wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx)); | ||||
wtx.nTimeSmart = ComputeTimeSmart(wtx); | wtx.nTimeSmart = ComputeTimeSmart(wtx); | ||||
AddToSpends(txid); | AddToSpends(txid); | ||||
} | } | ||||
bool fUpdated = false; | bool fUpdated = false; | ||||
if (!fInsertedNew) { | if (!fInsertedNew) { | ||||
// Merge | // Merge | ||||
if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) { | if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) { | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void CWallet::LoadToWallet(const CWalletTx &wtxIn) { | void CWallet::LoadToWallet(const CWalletTx &wtxIn) { | ||||
const TxId &txid = wtxIn.GetId(); | const TxId &txid = wtxIn.GetId(); | ||||
const auto &ins = mapWallet.emplace(txid, wtxIn); | const auto &ins = mapWallet.emplace(txid, wtxIn); | ||||
CWalletTx &wtx = ins.first->second; | CWalletTx &wtx = ins.first->second; | ||||
wtx.BindWallet(this); | wtx.BindWallet(this); | ||||
if (/* insertion took place */ ins.second) { | if (/* insertion took place */ ins.second) { | ||||
wtx.m_it_wtxOrdered = wtxOrdered.insert( | wtx.m_it_wtxOrdered = | ||||
std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr))); | wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx)); | ||||
} | } | ||||
AddToSpends(txid); | AddToSpends(txid); | ||||
for (const CTxIn &txin : wtx.tx->vin) { | for (const CTxIn &txin : wtx.tx->vin) { | ||||
auto it = mapWallet.find(txin.prevout.GetTxId()); | auto it = mapWallet.find(txin.prevout.GetTxId()); | ||||
if (it != mapWallet.end()) { | if (it != mapWallet.end()) { | ||||
CWalletTx &prevtx = it->second; | CWalletTx &prevtx = it->second; | ||||
if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { | if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { | ||||
MarkConflicted(prevtx.hashBlock, wtx.GetId()); | MarkConflicted(prevtx.hashBlock, wtx.GetId()); | ||||
▲ Show 20 Lines • Show All 3,182 Lines • ▼ Show 20 Lines | if (!wtx.hashUnset()) { | ||||
int64_t latestNow = wtx.nTimeReceived; | int64_t latestNow = wtx.nTimeReceived; | ||||
int64_t latestEntry = 0; | int64_t latestEntry = 0; | ||||
// Tolerate times up to the last timestamp in the wallet not more | // Tolerate times up to the last timestamp in the wallet not more | ||||
// than 5 minutes into the future | // than 5 minutes into the future | ||||
int64_t latestTolerated = latestNow + 300; | int64_t latestTolerated = latestNow + 300; | ||||
const TxItems &txOrdered = wtxOrdered; | const TxItems &txOrdered = wtxOrdered; | ||||
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { | for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { | ||||
CWalletTx *const pwtx = it->second.first; | CWalletTx *const pwtx = it->second; | ||||
if (pwtx == &wtx) { | if (pwtx == &wtx) { | ||||
continue; | continue; | ||||
} | } | ||||
CAccountingEntry *const pacentry = it->second.second; | |||||
int64_t nSmartTime; | int64_t nSmartTime; | ||||
if (pwtx) { | |||||
nSmartTime = pwtx->nTimeSmart; | nSmartTime = pwtx->nTimeSmart; | ||||
if (!nSmartTime) { | if (!nSmartTime) { | ||||
nSmartTime = pwtx->nTimeReceived; | nSmartTime = pwtx->nTimeReceived; | ||||
} | } | ||||
} else { | |||||
nSmartTime = pacentry->nTime; | |||||
} | |||||
if (nSmartTime <= latestTolerated) { | if (nSmartTime <= latestTolerated) { | ||||
latestEntry = nSmartTime; | latestEntry = nSmartTime; | ||||
if (nSmartTime > latestNow) { | if (nSmartTime > latestNow) { | ||||
latestNow = nSmartTime; | latestNow = nSmartTime; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 691 Lines • Show Last 20 Lines |