Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1823,7 +1823,7 @@ bool AppInit2()
copyTo->fFromMe = copyFrom->fFromMe;
copyTo->strFromAccount = copyFrom->strFromAccount;
copyTo->nOrderPos = copyFrom->nOrderPos;
copyTo->WriteToDisk(&walletdb);
walletdb.WriteTx(*copyTo);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2440,7 +2440,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CWalletTx wtx(pwalletMain, tx);
wtx.nTimeReceived = pindex->GetBlockTime();
wtx.SetMerkleBranch(block);
pwalletMain->AddToWallet(wtx, false, nullptr);
pwalletMain->AddToWallet(wtx, nullptr);
setAddedTx.insert(pSpend.second);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/test/accounting_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
pwalletMain->AddAccountingEntry(ae, walletdb);

wtx.mapValue["comment"] = "z";
pwalletMain->AddToWallet(wtx, false, &walletdb);
pwalletMain->AddToWallet(wtx, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
vpwtx[0]->nOrderPos = -1;
Expand Down Expand Up @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
pwalletMain->AddToWallet(wtx, false, &walletdb);
pwalletMain->AddToWallet(wtx, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;

Expand All @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
pwalletMain->AddToWallet(wtx, false, &walletdb);
pwalletMain->AddToWallet(wtx, &walletdb);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
vpwtx[2]->nOrderPos = -1;
Expand Down
173 changes: 87 additions & 86 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,83 +811,89 @@ void CWallet::MarkDirty()
}
}

bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
bool CWallet::AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb)
{
uint256 hash = wtxIn.GetHash();

if (fFromLoadWallet) {
mapWallet[hash] = wtxIn;
CWalletTx& wtx = mapWallet[hash];
wtx.BindWallet(this);
LOCK(cs_wallet);
// 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));
CWalletTx& wtx = (*ret.first).second;
wtx.BindWallet(this);
bool fInsertedNew = ret.second;
if (fInsertedNew) {
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(pwalletdb);
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
wtx.UpdateTimeSmart();
AddToSpends(hash);
for (const CTxIn& txin : wtx.vin) {
if (mapWallet.count(txin.prevout.hash)) {
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
MarkConflicted(prevtx.hashBlock, wtx.GetHash());
}
}
}
} else {
LOCK(cs_wallet);
// 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));
CWalletTx& wtx = (*ret.first).second;
wtx.BindWallet(this);
bool fInsertedNew = ret.second;
if (fInsertedNew) {
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(pwalletdb);
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
}

bool fUpdated = false;
if (!fInsertedNew) {
// Merge
if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) {
wtx.hashBlock = wtxIn.hashBlock;
wtx.UpdateTimeSmart();
AddToSpends(hash);
fUpdated = true;
}

bool fUpdated = false;
if (!fInsertedNew) {
// Merge
if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) {
wtx.hashBlock = wtxIn.hashBlock;
wtx.UpdateTimeSmart();
fUpdated = true;
}
// If no longer abandoned, update
if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned()) {
wtx.hashBlock = wtxIn.hashBlock;
if (!fUpdated) wtx.UpdateTimeSmart();
fUpdated = true;
}
if (wtxIn.nIndex != -1 && wtxIn.nIndex != wtx.nIndex) {
wtx.nIndex = wtxIn.nIndex;
fUpdated = true;
}
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) {
wtx.fFromMe = wtxIn.fFromMe;
fUpdated = true;
}
// If no longer abandoned, update
if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned()) {
wtx.hashBlock = wtxIn.hashBlock;
if (!fUpdated) wtx.UpdateTimeSmart();
fUpdated = true;
}
if (wtxIn.nIndex != -1 && wtxIn.nIndex != wtx.nIndex) {
wtx.nIndex = wtxIn.nIndex;
fUpdated = true;
}
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) {
wtx.fFromMe = wtxIn.fFromMe;
fUpdated = true;
}
}

//// debug print
LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
//// debug print
LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));

// Write to disk
if (fInsertedNew || fUpdated)
if (!wtx.WriteToDisk(pwalletdb))
return false;
// Write to disk
if (fInsertedNew || fUpdated) {
if (!pwalletdb) {
CWalletDB(strWalletFile).WriteTx(wtx);
} else if (!pwalletdb->WriteTx(wtx)) {
return false;
}
}

// Break debit/credit balance caches:
wtx.MarkDirty();
// Break debit/credit balance caches:
wtx.MarkDirty();

// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);

// notify an external script when a wallet transaction comes in or is updated
std::string strCmd = GetArg("-walletnotify", "");
// notify an external script when a wallet transaction comes in or is updated
std::string strCmd = GetArg("-walletnotify", "");

if (!strCmd.empty()) {
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
if (!strCmd.empty()) {
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
return true;
}

bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
mapWallet[hash] = wtxIn;
CWalletTx& wtx = mapWallet[hash];
wtx.BindWallet(this);
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
AddToSpends(hash);
for (const CTxIn& txin : wtx.vin) {
if (mapWallet.count(txin.prevout.hash)) {
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
MarkConflicted(prevtx.hashBlock, wtx.GetHash());
}
}
}
return true;
Expand Down Expand Up @@ -939,7 +945,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
// this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
CWalletDB walletdb(strWalletFile, "r+", false);

return AddToWallet(wtx, false, &walletdb);
return AddToWallet(wtx, &walletdb);
}
}
return false;
Expand Down Expand Up @@ -979,7 +985,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
wtx.nIndex = -1;
wtx.setAbandoned();
wtx.MarkDirty();
wtx.WriteToDisk(&walletdb);
walletdb.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));
Expand Down Expand Up @@ -1036,7 +1042,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
wtx.nIndex = -1;
wtx.hashBlock = hashBlock;
wtx.MarkDirty();
wtx.WriteToDisk(&walletdb);
walletdb.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) {
Expand Down Expand Up @@ -1573,13 +1579,6 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
}
}

bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
{
if (pwalletdb)
return pwalletdb->WriteTx(GetHash(), *this);
return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
}

bool CWallet::Upgrade(std::string& error, const int& prevVersion)
{
LOCK(cs_wallet);
Expand Down Expand Up @@ -2304,18 +2303,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
return true;
}

bool CWallet::SelectCoinsToSpend(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX, bool fIncludeColdStaking, bool fIncludeDelegated) const
bool CWallet::SelectCoinsToSpend(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
{
// Note: this function should never be used for "always free" tx types like dstx
std::vector<COutput> vCoins;
AvailableCoins(&vCoins,
coinControl,
fIncludeDelegated,
fIncludeColdStaking,
coin_type,
true, // fOnlyConfirmed
false, // fIncludeZeroValue
useIX);
std::vector<COutput> vCoins(vAvailableCoins);

// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) {
Expand Down Expand Up @@ -2500,6 +2491,16 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
{
LOCK2(cs_main, cs_wallet);
{
std::vector<COutput> vAvailableCoins;
AvailableCoins(&vAvailableCoins,
coinControl,
fIncludeDelegated,
false, // fIncludeColdStaking
coin_type,
true, // fOnlyConfirmed
false, // fIncludeZeroValue
useIX);

nFeeRet = 0;
if (nFeePay > 0) nFeeRet = nFeePay;
while (true) {
Expand Down Expand Up @@ -2545,7 +2546,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
std::set<std::pair<const CWalletTx*, unsigned int> > setCoins;
CAmount nValueIn = 0;

if (!SelectCoinsToSpend(nTotalValue, setCoins, nValueIn, coinControl, coin_type, useIX, false, fIncludeDelegated)) {
if (!SelectCoinsToSpend(vAvailableCoins, nTotalValue, setCoins, nValueIn, coinControl)) {
if (coin_type == ALL_COINS) {
strFailReason = _("Insufficient funds.");
}
Expand Down Expand Up @@ -2934,7 +2935,7 @@ CWallet::CommitResult CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey&

// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
AddToWallet(wtxNew, false, pwalletdb);
AddToWallet(wtxNew, pwalletdb);

// Notify that old coins are spent
if (!wtxNew.HasZerocoinSpendInputs()) {
Expand Down
7 changes: 3 additions & 4 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
int nWatchonlyConfig = 1
) const;
//! >> Available coins (spending)
bool SelectCoinsToSpend(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl = nullptr, AvailableCoinsType coin_type = ALL_COINS, bool useIX = true, bool fIncludeColdStaking = false, bool fIncludeDelegated = true) const;
bool SelectCoinsToSpend(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl = nullptr) const;
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
//! >> Available coins (staking)
bool StakeableCoins(std::vector<COutput>* pCoins = nullptr);
Expand Down Expand Up @@ -432,7 +432,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface

bool GetLabelDestination(CTxDestination& dest, const std::string& label, bool bForceNew = false);
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
bool AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb = nullptr);
bool LoadToWallet(const CWalletTx& wtxIn);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256& hash);
Expand Down Expand Up @@ -937,8 +938,6 @@ class CWalletTx : public CMerkleTx
bool IsTrusted() const;
bool IsTrusted(int& nDepth, bool& fConflicted) const;

bool WriteToDisk(CWalletDB *pwalletdb);

int64_t GetTxTime() const;
void UpdateTimeSmart();
int GetRequestCount() const;
Expand Down
10 changes: 7 additions & 3 deletions src/wallet/wallet_zerocoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void CWallet::doZPivRescan(const CBlockIndex* pindex, const CBlock& block,
CWalletTx wtx(this, tx);
wtx.nTimeReceived = block.GetBlockTime();
wtx.SetMerkleBranch(block);
AddToWallet(wtx, false, &walletdb);
AddToWallet(wtx, &walletdb);
setAddedToWallet.insert(txid);
}
}
Expand All @@ -137,7 +137,7 @@ void CWallet::doZPivRescan(const CBlockIndex* pindex, const CBlock& block,
wtx.SetMerkleBranch(blockSpend);

wtx.nTimeReceived = pindexSpend->nTime;
AddToWallet(wtx, false, &walletdb);
AddToWallet(wtx, &walletdb);
setAddedToWallet.emplace(txidSpend);
}
}
Expand Down Expand Up @@ -302,10 +302,14 @@ bool CWallet::CreateZerocoinMintTransaction(const CAmount nValue,
// calculate fee
CAmount nTotalValue = nValue + Params().GetConsensus().ZC_MinMintFee * txNew.vout.size();

// Get the available coins
std::vector<COutput> vAvailableCoins;
AvailableCoins(&vAvailableCoins, coinControl);

CAmount nValueIn = 0;
std::set<std::pair<const CWalletTx*, unsigned int> > setCoins;
// select UTXO's to use
if (!SelectCoinsToSpend(nTotalValue, setCoins, nValueIn, coinControl)) {
if (!SelectCoinsToSpend(vAvailableCoins, nTotalValue, setCoins, nValueIn, coinControl)) {
strFailReason = _("Insufficient or insufficient confirmed funds, you might need to wait a few minutes and try again.");
return false;
}
Expand Down
Loading